3
0
mirror of https://github.com/ergochat/ergo.git synced 2025-01-09 19:52:57 +01:00

Merge pull request #2034 from slingamn/deps

dependency upgrades for v2.12 release cycle
This commit is contained in:
Shivaram Lingamneni 2023-01-15 05:44:03 -08:00 committed by GitHub
commit 8690a7648b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
342 changed files with 48788 additions and 14627 deletions

18
go.mod
View File

@ -8,8 +8,8 @@ require (
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
github.com/ergochat/confusables v0.0.0-20201108231250-4ab98ab61fb1 github.com/ergochat/confusables v0.0.0-20201108231250-4ab98ab61fb1
github.com/ergochat/go-ident v0.0.0-20200511222032-830550b1d775 github.com/ergochat/go-ident v0.0.0-20200511222032-830550b1d775
github.com/ergochat/irc-go v0.1.0 github.com/ergochat/irc-go v0.2.0
github.com/go-sql-driver/mysql v1.6.0 github.com/go-sql-driver/mysql v1.7.0
github.com/go-test/deep v1.0.6 // indirect github.com/go-test/deep v1.0.6 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
@ -17,27 +17,27 @@ require (
github.com/onsi/ginkgo v1.12.0 // indirect github.com/onsi/ginkgo v1.12.0 // indirect
github.com/onsi/gomega v1.9.0 // indirect github.com/onsi/gomega v1.9.0 // indirect
github.com/stretchr/testify v1.4.0 // indirect github.com/stretchr/testify v1.4.0 // indirect
github.com/tidwall/buntdb v1.2.9 github.com/tidwall/buntdb v1.2.10
github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208
github.com/xdg-go/scram v1.0.2 github.com/xdg-go/scram v1.0.2
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e golang.org/x/crypto v0.5.0
golang.org/x/text v0.3.7 golang.org/x/text v0.6.0
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
) )
require github.com/gofrs/flock v0.8.1 require github.com/gofrs/flock v0.8.1
require ( require (
github.com/tidwall/btree v1.1.0 // indirect github.com/tidwall/btree v1.4.2 // indirect
github.com/tidwall/gjson v1.12.1 // indirect github.com/tidwall/gjson v1.14.3 // indirect
github.com/tidwall/grect v0.1.4 // indirect github.com/tidwall/grect v0.1.4 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/pretty v1.2.0 // indirect
github.com/tidwall/rtred v0.1.2 // indirect github.com/tidwall/rtred v0.1.2 // indirect
github.com/tidwall/tinyqueue v0.1.1 // indirect github.com/tidwall/tinyqueue v0.1.1 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect golang.org/x/sys v0.4.0 // indirect
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect golang.org/x/term v0.4.0 // indirect
) )
replace github.com/gorilla/websocket => github.com/ergochat/websocket v1.4.2-oragono1 replace github.com/gorilla/websocket => github.com/ergochat/websocket v1.4.2-oragono1

20
go.sum
View File

@ -14,6 +14,8 @@ github.com/ergochat/irc-go v0.0.0-20210617222258-256f1601d3ce h1:RfyjeynouKZjmnN
github.com/ergochat/irc-go v0.0.0-20210617222258-256f1601d3ce/go.mod h1:2vi7KNpIPWnReB5hmLpl92eMywQvuIeIIGdt/FQCph0= github.com/ergochat/irc-go v0.0.0-20210617222258-256f1601d3ce/go.mod h1:2vi7KNpIPWnReB5hmLpl92eMywQvuIeIIGdt/FQCph0=
github.com/ergochat/irc-go v0.1.0 h1:jBHUayERH9SiPOWe4ePDWRztBjIQsU/jwLbbGUuiOWM= github.com/ergochat/irc-go v0.1.0 h1:jBHUayERH9SiPOWe4ePDWRztBjIQsU/jwLbbGUuiOWM=
github.com/ergochat/irc-go v0.1.0/go.mod h1:2vi7KNpIPWnReB5hmLpl92eMywQvuIeIIGdt/FQCph0= github.com/ergochat/irc-go v0.1.0/go.mod h1:2vi7KNpIPWnReB5hmLpl92eMywQvuIeIIGdt/FQCph0=
github.com/ergochat/irc-go v0.2.0 h1:3vHdy4c56UTY6+/rTBrQc1fmt32N5G8PrEZacJDOr+E=
github.com/ergochat/irc-go v0.2.0/go.mod h1:2vi7KNpIPWnReB5hmLpl92eMywQvuIeIIGdt/FQCph0=
github.com/ergochat/scram v1.0.2-ergo1 h1:2bYXiRFQH636pT0msOG39fmEYl4Eq+OuutcyDsCix/g= github.com/ergochat/scram v1.0.2-ergo1 h1:2bYXiRFQH636pT0msOG39fmEYl4Eq+OuutcyDsCix/g=
github.com/ergochat/scram v1.0.2-ergo1/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/ergochat/scram v1.0.2-ergo1/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
github.com/ergochat/websocket v1.4.2-oragono1 h1:plMUunFBM6UoSCIYCKKclTdy/TkkHfUslhOfJQzfueM= github.com/ergochat/websocket v1.4.2-oragono1 h1:plMUunFBM6UoSCIYCKKclTdy/TkkHfUslhOfJQzfueM=
@ -21,6 +23,8 @@ github.com/ergochat/websocket v1.4.2-oragono1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-test/deep v1.0.6 h1:UHSEyLZUwX9Qoi99vVwvewiMC8mM2bf7XEM2nqvzEn8= github.com/go-test/deep v1.0.6 h1:UHSEyLZUwX9Qoi99vVwvewiMC8mM2bf7XEM2nqvzEn8=
github.com/go-test/deep v1.0.6/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/go-test/deep v1.0.6/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
@ -49,14 +53,20 @@ github.com/tidwall/btree v0.6.1 h1:75VVgBeviiDO+3g4U+7+BaNBNhNINxB0ULPT3fs9pMY=
github.com/tidwall/btree v0.6.1/go.mod h1:TzIRzen6yHbibdSfK6t8QimqbUnoxUSrZfeW7Uob0q4= github.com/tidwall/btree v0.6.1/go.mod h1:TzIRzen6yHbibdSfK6t8QimqbUnoxUSrZfeW7Uob0q4=
github.com/tidwall/btree v1.1.0 h1:5P+9WU8ui5uhmcg3SoPyTwoI0mVyZ1nps7YQzTZFkYM= github.com/tidwall/btree v1.1.0 h1:5P+9WU8ui5uhmcg3SoPyTwoI0mVyZ1nps7YQzTZFkYM=
github.com/tidwall/btree v1.1.0/go.mod h1:TzIRzen6yHbibdSfK6t8QimqbUnoxUSrZfeW7Uob0q4= github.com/tidwall/btree v1.1.0/go.mod h1:TzIRzen6yHbibdSfK6t8QimqbUnoxUSrZfeW7Uob0q4=
github.com/tidwall/btree v1.4.2 h1:PpkaieETJMUxYNADsjgtNRcERX7mGc/GP2zp/r5FM3g=
github.com/tidwall/btree v1.4.2/go.mod h1:LGm8L/DZjPLmeWGjv5kFrY8dL4uVhMmzmmLYmsObdKE=
github.com/tidwall/buntdb v1.2.7 h1:SIyObKAymzLyGhDeIhVk2Yc1/EwfCC75Uyu77CHlVoA= github.com/tidwall/buntdb v1.2.7 h1:SIyObKAymzLyGhDeIhVk2Yc1/EwfCC75Uyu77CHlVoA=
github.com/tidwall/buntdb v1.2.7/go.mod h1:b6KvZM27x/8JLI5hgRhRu60pa3q0Tz9c50TyD46OHUM= github.com/tidwall/buntdb v1.2.7/go.mod h1:b6KvZM27x/8JLI5hgRhRu60pa3q0Tz9c50TyD46OHUM=
github.com/tidwall/buntdb v1.2.9 h1:XVz684P7X6HCTrdr385yDZWB1zt/n20ZNG3M1iGyFm4= github.com/tidwall/buntdb v1.2.9 h1:XVz684P7X6HCTrdr385yDZWB1zt/n20ZNG3M1iGyFm4=
github.com/tidwall/buntdb v1.2.9/go.mod h1:IwyGSvvDg6hnKSIhtdZ0AqhCZGH8ukdtCAzaP8fI1X4= github.com/tidwall/buntdb v1.2.9/go.mod h1:IwyGSvvDg6hnKSIhtdZ0AqhCZGH8ukdtCAzaP8fI1X4=
github.com/tidwall/buntdb v1.2.10 h1:U/ebfkmYPBnyiNZIirUiWFcxA/mgzjbKlyPynFsPtyM=
github.com/tidwall/buntdb v1.2.10/go.mod h1:lZZrZUWzlyDJKlLQ6DKAy53LnG7m5kHyrEHvvcDmBpU=
github.com/tidwall/gjson v1.10.2 h1:APbLGOM0rrEkd8WBw9C24nllro4ajFuJu0Sc9hRz8Bo= github.com/tidwall/gjson v1.10.2 h1:APbLGOM0rrEkd8WBw9C24nllro4ajFuJu0Sc9hRz8Bo=
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo= github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo=
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/grect v0.1.3 h1:z9YwQAMUxVSBde3b7Sl8Da37rffgNfZ6Fq6h9t6KdXE= github.com/tidwall/grect v0.1.3 h1:z9YwQAMUxVSBde3b7Sl8Da37rffgNfZ6Fq6h9t6KdXE=
github.com/tidwall/grect v0.1.3/go.mod h1:8GMjwh3gPZVpLBI/jDz9uslCe0dpxRpWDdtN0lWAS/E= github.com/tidwall/grect v0.1.3/go.mod h1:8GMjwh3gPZVpLBI/jDz9uslCe0dpxRpWDdtN0lWAS/E=
github.com/tidwall/grect v0.1.4 h1:dA3oIgNgWdSspFzn1kS4S/RDpZFLrIxAZOdJKjYapOg= github.com/tidwall/grect v0.1.4 h1:dA3oIgNgWdSspFzn1kS4S/RDpZFLrIxAZOdJKjYapOg=
@ -81,6 +91,8 @@ golang.org/x/crypto v0.0.0-20211115234514-b4de73f9ece8 h1:5QRxNnVsaJP6NAse0UdkRg
golang.org/x/crypto v0.0.0-20211115234514-b4de73f9ece8/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211115234514-b4de73f9ece8/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@ -91,13 +103,21 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg=
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -23,6 +23,7 @@ Asta Xie <xiemengjun at gmail.com>
Bulat Gaifullin <gaifullinbf at gmail.com> Bulat Gaifullin <gaifullinbf at gmail.com>
Caine Jette <jette at alum.mit.edu> Caine Jette <jette at alum.mit.edu>
Carlos Nieto <jose.carlos at menteslibres.net> Carlos Nieto <jose.carlos at menteslibres.net>
Chris Kirkland <chriskirkland at github.com>
Chris Moos <chris at tech9computers.com> Chris Moos <chris at tech9computers.com>
Craig Wilson <craiggwilson at gmail.com> Craig Wilson <craiggwilson at gmail.com>
Daniel Montoya <dsmontoyam at gmail.com> Daniel Montoya <dsmontoyam at gmail.com>
@ -45,6 +46,7 @@ Ilia Cimpoes <ichimpoesh at gmail.com>
INADA Naoki <songofacandy at gmail.com> INADA Naoki <songofacandy at gmail.com>
Jacek Szwec <szwec.jacek at gmail.com> Jacek Szwec <szwec.jacek at gmail.com>
James Harr <james.harr at gmail.com> James Harr <james.harr at gmail.com>
Janek Vedock <janekvedock at comcast.net>
Jeff Hodges <jeff at somethingsimilar.com> Jeff Hodges <jeff at somethingsimilar.com>
Jeffrey Charles <jeffreycharles at gmail.com> Jeffrey Charles <jeffreycharles at gmail.com>
Jerome Meyer <jxmeyer at gmail.com> Jerome Meyer <jxmeyer at gmail.com>
@ -59,12 +61,14 @@ Kamil Dziedzic <kamil at klecza.pl>
Kei Kamikawa <x00.x7f.x86 at gmail.com> Kei Kamikawa <x00.x7f.x86 at gmail.com>
Kevin Malachowski <kevin at chowski.com> Kevin Malachowski <kevin at chowski.com>
Kieron Woodhouse <kieron.woodhouse at infosum.com> Kieron Woodhouse <kieron.woodhouse at infosum.com>
Lance Tian <lance6716 at gmail.com>
Lennart Rudolph <lrudolph at hmc.edu> Lennart Rudolph <lrudolph at hmc.edu>
Leonardo YongUk Kim <dalinaum at gmail.com> Leonardo YongUk Kim <dalinaum at gmail.com>
Linh Tran Tuan <linhduonggnu at gmail.com> Linh Tran Tuan <linhduonggnu at gmail.com>
Lion Yang <lion at aosc.xyz> Lion Yang <lion at aosc.xyz>
Luca Looz <luca.looz92 at gmail.com> Luca Looz <luca.looz92 at gmail.com>
Lucas Liu <extrafliu at gmail.com> Lucas Liu <extrafliu at gmail.com>
Lunny Xiao <xiaolunwen at gmail.com>
Luke Scott <luke at webconnex.com> Luke Scott <luke at webconnex.com>
Maciej Zimnoch <maciej.zimnoch at codilime.com> Maciej Zimnoch <maciej.zimnoch at codilime.com>
Michael Woolnough <michael.woolnough at gmail.com> Michael Woolnough <michael.woolnough at gmail.com>
@ -79,6 +83,7 @@ Reed Allman <rdallman10 at gmail.com>
Richard Wilkes <wilkes at me.com> Richard Wilkes <wilkes at me.com>
Robert Russell <robert at rrbrussell.com> Robert Russell <robert at rrbrussell.com>
Runrioter Wung <runrioter at gmail.com> Runrioter Wung <runrioter at gmail.com>
Santhosh Kumar Tekuri <santhosh.tekuri at gmail.com>
Sho Iizuka <sho.i518 at gmail.com> Sho Iizuka <sho.i518 at gmail.com>
Sho Ikeda <suicaicoca at gmail.com> Sho Ikeda <suicaicoca at gmail.com>
Shuode Li <elemount at qq.com> Shuode Li <elemount at qq.com>
@ -99,12 +104,14 @@ Xiuming Chen <cc at cxm.cc>
Xuehong Chan <chanxuehong at gmail.com> Xuehong Chan <chanxuehong at gmail.com>
Zhenye Xie <xiezhenye at gmail.com> Zhenye Xie <xiezhenye at gmail.com>
Zhixin Wen <john.wenzhixin at gmail.com> Zhixin Wen <john.wenzhixin at gmail.com>
Ziheng Lyu <zihenglv at gmail.com>
# Organizations # Organizations
Barracuda Networks, Inc. Barracuda Networks, Inc.
Counting Ltd. Counting Ltd.
DigitalOcean Inc. DigitalOcean Inc.
dyves labs AG
Facebook Inc. Facebook Inc.
GitHub Inc. GitHub Inc.
Google Inc. Google Inc.

View File

@ -1,3 +1,24 @@
## Version 1.7 (2022-11-29)
Changes:
- Drop support of Go 1.12 (#1211)
- Refactoring `(*textRows).readRow` in a more clear way (#1230)
- util: Reduce boundary check in escape functions. (#1316)
- enhancement for mysqlConn handleAuthResult (#1250)
New Features:
- support Is comparison on MySQLError (#1210)
- return unsigned in database type name when necessary (#1238)
- Add API to express like a --ssl-mode=PREFERRED MySQL client (#1370)
- Add SQLState to MySQLError (#1321)
Bugfixes:
- Fix parsing 0 year. (#1257)
## Version 1.6 (2021-04-01) ## Version 1.6 (2021-04-01)
Changes: Changes:

View File

@ -40,7 +40,7 @@ A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) pac
* Optional placeholder interpolation * Optional placeholder interpolation
## Requirements ## Requirements
* Go 1.10 or higher. We aim to support the 3 latest versions of Go. * Go 1.13 or higher. We aim to support the 3 latest versions of Go.
* MySQL (4.1+), MariaDB, Percona Server, Google CloudSQL or Sphinx (2.2.3+) * MySQL (4.1+), MariaDB, Percona Server, Google CloudSQL or Sphinx (2.2.3+)
--------------------------------------- ---------------------------------------
@ -85,7 +85,7 @@ db.SetMaxIdleConns(10)
`db.SetMaxOpenConns()` is highly recommended to limit the number of connection used by the application. There is no recommended limit number because it depends on application and MySQL server. `db.SetMaxOpenConns()` is highly recommended to limit the number of connection used by the application. There is no recommended limit number because it depends on application and MySQL server.
`db.SetMaxIdleConns()` is recommended to be set same to (or greater than) `db.SetMaxOpenConns()`. When it is smaller than `SetMaxOpenConns()`, connections can be opened and closed very frequently than you expect. Idle connections can be closed by the `db.SetConnMaxLifetime()`. If you want to close idle connections more rapidly, you can use `db.SetConnMaxIdleTime()` since Go 1.15. `db.SetMaxIdleConns()` is recommended to be set same to `db.SetMaxOpenConns()`. When it is smaller than `SetMaxOpenConns()`, connections can be opened and closed much more frequently than you expect. Idle connections can be closed by the `db.SetConnMaxLifetime()`. If you want to close idle connections more rapidly, you can use `db.SetConnMaxIdleTime()` since Go 1.15.
### DSN (Data Source Name) ### DSN (Data Source Name)
@ -157,6 +157,17 @@ Default: false
`allowCleartextPasswords=true` allows using the [cleartext client side plugin](https://dev.mysql.com/doc/en/cleartext-pluggable-authentication.html) if required by an account, such as one defined with the [PAM authentication plugin](http://dev.mysql.com/doc/en/pam-authentication-plugin.html). Sending passwords in clear text may be a security problem in some configurations. To avoid problems if there is any possibility that the password would be intercepted, clients should connect to MySQL Server using a method that protects the password. Possibilities include [TLS / SSL](#tls), IPsec, or a private network. `allowCleartextPasswords=true` allows using the [cleartext client side plugin](https://dev.mysql.com/doc/en/cleartext-pluggable-authentication.html) if required by an account, such as one defined with the [PAM authentication plugin](http://dev.mysql.com/doc/en/pam-authentication-plugin.html). Sending passwords in clear text may be a security problem in some configurations. To avoid problems if there is any possibility that the password would be intercepted, clients should connect to MySQL Server using a method that protects the password. Possibilities include [TLS / SSL](#tls), IPsec, or a private network.
##### `allowFallbackToPlaintext`
```
Type: bool
Valid Values: true, false
Default: false
```
`allowFallbackToPlaintext=true` acts like a `--ssl-mode=PREFERRED` MySQL client as described in [Command Options for Connecting to the Server](https://dev.mysql.com/doc/refman/5.7/en/connection-options.html#option_general_ssl-mode)
##### `allowNativePasswords` ##### `allowNativePasswords`
``` ```
@ -454,7 +465,7 @@ user:password@/
The connection pool is managed by Go's database/sql package. For details on how to configure the size of the pool and how long connections stay in the pool see `*DB.SetMaxOpenConns`, `*DB.SetMaxIdleConns`, and `*DB.SetConnMaxLifetime` in the [database/sql documentation](https://golang.org/pkg/database/sql/). The read, write, and dial timeouts for each individual connection are configured with the DSN parameters [`readTimeout`](#readtimeout), [`writeTimeout`](#writetimeout), and [`timeout`](#timeout), respectively. The connection pool is managed by Go's database/sql package. For details on how to configure the size of the pool and how long connections stay in the pool see `*DB.SetMaxOpenConns`, `*DB.SetMaxIdleConns`, and `*DB.SetConnMaxLifetime` in the [database/sql documentation](https://golang.org/pkg/database/sql/). The read, write, and dial timeouts for each individual connection are configured with the DSN parameters [`readTimeout`](#readtimeout), [`writeTimeout`](#writetimeout), and [`timeout`](#timeout), respectively.
## `ColumnType` Support ## `ColumnType` Support
This driver supports the [`ColumnType` interface](https://golang.org/pkg/database/sql/#ColumnType) introduced in Go 1.8, with the exception of [`ColumnType.Length()`](https://golang.org/pkg/database/sql/#ColumnType.Length), which is currently not supported. This driver supports the [`ColumnType` interface](https://golang.org/pkg/database/sql/#ColumnType) introduced in Go 1.8, with the exception of [`ColumnType.Length()`](https://golang.org/pkg/database/sql/#ColumnType.Length), which is currently not supported. All Unsigned database type names will be returned `UNSIGNED ` with `INT`, `TINYINT`, `SMALLINT`, `BIGINT`.
## `context.Context` Support ## `context.Context` Support
Go 1.8 added `database/sql` support for `context.Context`. This driver supports query timeouts and cancellation via contexts. Go 1.8 added `database/sql` support for `context.Context`. This driver supports query timeouts and cancellation via contexts.

19
vendor/github.com/go-sql-driver/mysql/atomic_bool.go generated vendored Normal file
View File

@ -0,0 +1,19 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package.
//
// Copyright 2022 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
//go:build go1.19
// +build go1.19
package mysql
import "sync/atomic"
/******************************************************************************
* Sync utils *
******************************************************************************/
type atomicBool = atomic.Bool

View File

@ -0,0 +1,47 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package.
//
// Copyright 2022 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
//go:build !go1.19
// +build !go1.19
package mysql
import "sync/atomic"
/******************************************************************************
* Sync utils *
******************************************************************************/
// atomicBool is an implementation of atomic.Bool for older version of Go.
// it is a wrapper around uint32 for usage as a boolean value with
// atomic access.
type atomicBool struct {
_ noCopy
value uint32
}
// Load returns whether the current boolean value is true
func (ab *atomicBool) Load() bool {
return atomic.LoadUint32(&ab.value) > 0
}
// Store sets the value of the bool regardless of the previous value
func (ab *atomicBool) Store(value bool) {
if value {
atomic.StoreUint32(&ab.value, 1)
} else {
atomic.StoreUint32(&ab.value, 0)
}
}
// Swap sets the value of the bool and returns the old value.
func (ab *atomicBool) Swap(value bool) bool {
if value {
return atomic.SwapUint32(&ab.value, 1) > 0
}
return atomic.SwapUint32(&ab.value, 0) > 0
}

View File

@ -33,27 +33,26 @@ var (
// Note: The provided rsa.PublicKey instance is exclusively owned by the driver // Note: The provided rsa.PublicKey instance is exclusively owned by the driver
// after registering it and may not be modified. // after registering it and may not be modified.
// //
// data, err := ioutil.ReadFile("mykey.pem") // data, err := ioutil.ReadFile("mykey.pem")
// if err != nil { // if err != nil {
// log.Fatal(err) // log.Fatal(err)
// } // }
// //
// block, _ := pem.Decode(data) // block, _ := pem.Decode(data)
// if block == nil || block.Type != "PUBLIC KEY" { // if block == nil || block.Type != "PUBLIC KEY" {
// log.Fatal("failed to decode PEM block containing public key") // log.Fatal("failed to decode PEM block containing public key")
// } // }
// //
// pub, err := x509.ParsePKIXPublicKey(block.Bytes) // pub, err := x509.ParsePKIXPublicKey(block.Bytes)
// if err != nil { // if err != nil {
// log.Fatal(err) // log.Fatal(err)
// } // }
//
// if rsaPubKey, ok := pub.(*rsa.PublicKey); ok {
// mysql.RegisterServerPubKey("mykey", rsaPubKey)
// } else {
// log.Fatal("not a RSA public key")
// }
// //
// if rsaPubKey, ok := pub.(*rsa.PublicKey); ok {
// mysql.RegisterServerPubKey("mykey", rsaPubKey)
// } else {
// log.Fatal("not a RSA public key")
// }
func RegisterServerPubKey(name string, pubKey *rsa.PublicKey) { func RegisterServerPubKey(name string, pubKey *rsa.PublicKey) {
serverPubKeyLock.Lock() serverPubKeyLock.Lock()
if serverPubKeyRegistry == nil { if serverPubKeyRegistry == nil {
@ -274,7 +273,9 @@ func (mc *mysqlConn) auth(authData []byte, plugin string) ([]byte, error) {
if len(mc.cfg.Passwd) == 0 { if len(mc.cfg.Passwd) == 0 {
return []byte{0}, nil return []byte{0}, nil
} }
if mc.cfg.tls != nil || mc.cfg.Net == "unix" { // unlike caching_sha2_password, sha256_password does not accept
// cleartext password on unix transport.
if mc.cfg.TLS != nil {
// write cleartext auth packet // write cleartext auth packet
return append([]byte(mc.cfg.Passwd), 0), nil return append([]byte(mc.cfg.Passwd), 0), nil
} }
@ -350,7 +351,7 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
} }
case cachingSha2PasswordPerformFullAuthentication: case cachingSha2PasswordPerformFullAuthentication:
if mc.cfg.tls != nil || mc.cfg.Net == "unix" { if mc.cfg.TLS != nil || mc.cfg.Net == "unix" {
// write cleartext auth packet // write cleartext auth packet
err = mc.writeAuthSwitchPacket(append([]byte(mc.cfg.Passwd), 0)) err = mc.writeAuthSwitchPacket(append([]byte(mc.cfg.Passwd), 0))
if err != nil { if err != nil {
@ -365,13 +366,20 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
return err return err
} }
data[4] = cachingSha2PasswordRequestPublicKey data[4] = cachingSha2PasswordRequestPublicKey
mc.writePacket(data) err = mc.writePacket(data)
if err != nil {
return err
}
// parse public key
if data, err = mc.readPacket(); err != nil { if data, err = mc.readPacket(); err != nil {
return err return err
} }
if data[0] != iAuthMoreData {
return fmt.Errorf("unexpect resp from server for caching_sha2_password perform full authentication")
}
// parse public key
block, rest := pem.Decode(data[1:]) block, rest := pem.Decode(data[1:])
if block == nil { if block == nil {
return fmt.Errorf("No Pem data found, data: %s", rest) return fmt.Errorf("No Pem data found, data: %s", rest)
@ -404,6 +412,10 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
return nil // auth successful return nil // auth successful
default: default:
block, _ := pem.Decode(authData) block, _ := pem.Decode(authData)
if block == nil {
return fmt.Errorf("no Pem data found, data: %s", authData)
}
pub, err := x509.ParsePKIXPublicKey(block.Bytes) pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil { if err != nil {
return err return err

View File

@ -13,7 +13,8 @@ const binaryCollation = "binary"
// A list of available collations mapped to the internal ID. // A list of available collations mapped to the internal ID.
// To update this map use the following MySQL query: // To update this map use the following MySQL query:
// SELECT COLLATION_NAME, ID FROM information_schema.COLLATIONS WHERE ID<256 ORDER BY ID //
// SELECT COLLATION_NAME, ID FROM information_schema.COLLATIONS WHERE ID<256 ORDER BY ID
// //
// Handshake packet have only 1 byte for collation_id. So we can't use collations with ID > 255. // Handshake packet have only 1 byte for collation_id. So we can't use collations with ID > 255.
// //

View File

@ -6,6 +6,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this file, // License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/. // You can obtain one at http://mozilla.org/MPL/2.0/.
//go:build linux || darwin || dragonfly || freebsd || netbsd || openbsd || solaris || illumos
// +build linux darwin dragonfly freebsd netbsd openbsd solaris illumos // +build linux darwin dragonfly freebsd netbsd openbsd solaris illumos
package mysql package mysql

View File

@ -6,6 +6,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this file, // License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/. // You can obtain one at http://mozilla.org/MPL/2.0/.
//go:build !linux && !darwin && !dragonfly && !freebsd && !netbsd && !openbsd && !solaris && !illumos
// +build !linux,!darwin,!dragonfly,!freebsd,!netbsd,!openbsd,!solaris,!illumos // +build !linux,!darwin,!dragonfly,!freebsd,!netbsd,!openbsd,!solaris,!illumos
package mysql package mysql

View File

@ -104,7 +104,7 @@ func (mc *mysqlConn) Begin() (driver.Tx, error) {
} }
func (mc *mysqlConn) begin(readOnly bool) (driver.Tx, error) { func (mc *mysqlConn) begin(readOnly bool) (driver.Tx, error) {
if mc.closed.IsSet() { if mc.closed.Load() {
errLog.Print(ErrInvalidConn) errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn return nil, driver.ErrBadConn
} }
@ -123,7 +123,7 @@ func (mc *mysqlConn) begin(readOnly bool) (driver.Tx, error) {
func (mc *mysqlConn) Close() (err error) { func (mc *mysqlConn) Close() (err error) {
// Makes Close idempotent // Makes Close idempotent
if !mc.closed.IsSet() { if !mc.closed.Load() {
err = mc.writeCommandPacket(comQuit) err = mc.writeCommandPacket(comQuit)
} }
@ -137,7 +137,7 @@ func (mc *mysqlConn) Close() (err error) {
// is called before auth or on auth failure because MySQL will have already // is called before auth or on auth failure because MySQL will have already
// closed the network connection. // closed the network connection.
func (mc *mysqlConn) cleanup() { func (mc *mysqlConn) cleanup() {
if !mc.closed.TrySet(true) { if mc.closed.Swap(true) {
return return
} }
@ -152,7 +152,7 @@ func (mc *mysqlConn) cleanup() {
} }
func (mc *mysqlConn) error() error { func (mc *mysqlConn) error() error {
if mc.closed.IsSet() { if mc.closed.Load() {
if err := mc.canceled.Value(); err != nil { if err := mc.canceled.Value(); err != nil {
return err return err
} }
@ -162,7 +162,7 @@ func (mc *mysqlConn) error() error {
} }
func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) { func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) {
if mc.closed.IsSet() { if mc.closed.Load() {
errLog.Print(ErrInvalidConn) errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn return nil, driver.ErrBadConn
} }
@ -295,7 +295,7 @@ func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (strin
} }
func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, error) { func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, error) {
if mc.closed.IsSet() { if mc.closed.Load() {
errLog.Print(ErrInvalidConn) errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn return nil, driver.ErrBadConn
} }
@ -356,7 +356,7 @@ func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, erro
} }
func (mc *mysqlConn) query(query string, args []driver.Value) (*textRows, error) { func (mc *mysqlConn) query(query string, args []driver.Value) (*textRows, error) {
if mc.closed.IsSet() { if mc.closed.Load() {
errLog.Print(ErrInvalidConn) errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn return nil, driver.ErrBadConn
} }
@ -450,7 +450,7 @@ func (mc *mysqlConn) finish() {
// Ping implements driver.Pinger interface // Ping implements driver.Pinger interface
func (mc *mysqlConn) Ping(ctx context.Context) (err error) { func (mc *mysqlConn) Ping(ctx context.Context) (err error) {
if mc.closed.IsSet() { if mc.closed.Load() {
errLog.Print(ErrInvalidConn) errLog.Print(ErrInvalidConn)
return driver.ErrBadConn return driver.ErrBadConn
} }
@ -469,7 +469,7 @@ func (mc *mysqlConn) Ping(ctx context.Context) (err error) {
// BeginTx implements driver.ConnBeginTx interface // BeginTx implements driver.ConnBeginTx interface
func (mc *mysqlConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { func (mc *mysqlConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
if mc.closed.IsSet() { if mc.closed.Load() {
return nil, driver.ErrBadConn return nil, driver.ErrBadConn
} }
@ -636,7 +636,7 @@ func (mc *mysqlConn) CheckNamedValue(nv *driver.NamedValue) (err error) {
// ResetSession implements driver.SessionResetter. // ResetSession implements driver.SessionResetter.
// (From Go 1.10) // (From Go 1.10)
func (mc *mysqlConn) ResetSession(ctx context.Context) error { func (mc *mysqlConn) ResetSession(ctx context.Context) error {
if mc.closed.IsSet() { if mc.closed.Load() {
return driver.ErrBadConn return driver.ErrBadConn
} }
mc.reset = true mc.reset = true
@ -646,5 +646,5 @@ func (mc *mysqlConn) ResetSession(ctx context.Context) error {
// IsValid implements driver.Validator interface // IsValid implements driver.Validator interface
// (From Go 1.15) // (From Go 1.15)
func (mc *mysqlConn) IsValid() bool { func (mc *mysqlConn) IsValid() bool {
return !mc.closed.IsSet() return !mc.closed.Load()
} }

View File

@ -8,10 +8,10 @@
// //
// The driver should be used via the database/sql package: // The driver should be used via the database/sql package:
// //
// import "database/sql" // import "database/sql"
// import _ "github.com/go-sql-driver/mysql" // import _ "github.com/go-sql-driver/mysql"
// //
// db, err := sql.Open("mysql", "user:password@/dbname") // db, err := sql.Open("mysql", "user:password@/dbname")
// //
// See https://github.com/go-sql-driver/mysql#usage for details // See https://github.com/go-sql-driver/mysql#usage for details
package mysql package mysql

View File

@ -46,22 +46,23 @@ type Config struct {
ServerPubKey string // Server public key name ServerPubKey string // Server public key name
pubKey *rsa.PublicKey // Server public key pubKey *rsa.PublicKey // Server public key
TLSConfig string // TLS configuration name TLSConfig string // TLS configuration name
tls *tls.Config // TLS configuration TLS *tls.Config // TLS configuration, its priority is higher than TLSConfig
Timeout time.Duration // Dial timeout Timeout time.Duration // Dial timeout
ReadTimeout time.Duration // I/O read timeout ReadTimeout time.Duration // I/O read timeout
WriteTimeout time.Duration // I/O write timeout WriteTimeout time.Duration // I/O write timeout
AllowAllFiles bool // Allow all files to be used with LOAD DATA LOCAL INFILE AllowAllFiles bool // Allow all files to be used with LOAD DATA LOCAL INFILE
AllowCleartextPasswords bool // Allows the cleartext client side plugin AllowCleartextPasswords bool // Allows the cleartext client side plugin
AllowNativePasswords bool // Allows the native password authentication method AllowFallbackToPlaintext bool // Allows fallback to unencrypted connection if server does not support TLS
AllowOldPasswords bool // Allows the old insecure password method AllowNativePasswords bool // Allows the native password authentication method
CheckConnLiveness bool // Check connections for liveness before using them AllowOldPasswords bool // Allows the old insecure password method
ClientFoundRows bool // Return number of matching rows instead of rows changed CheckConnLiveness bool // Check connections for liveness before using them
ColumnsWithAlias bool // Prepend table alias to column names ClientFoundRows bool // Return number of matching rows instead of rows changed
InterpolateParams bool // Interpolate placeholders into query string ColumnsWithAlias bool // Prepend table alias to column names
MultiStatements bool // Allow multiple statements in one query InterpolateParams bool // Interpolate placeholders into query string
ParseTime bool // Parse time values to time.Time MultiStatements bool // Allow multiple statements in one query
RejectReadOnly bool // Reject read-only connections ParseTime bool // Parse time values to time.Time
RejectReadOnly bool // Reject read-only connections
} }
// NewConfig creates a new Config and sets default values. // NewConfig creates a new Config and sets default values.
@ -77,8 +78,8 @@ func NewConfig() *Config {
func (cfg *Config) Clone() *Config { func (cfg *Config) Clone() *Config {
cp := *cfg cp := *cfg
if cp.tls != nil { if cp.TLS != nil {
cp.tls = cfg.tls.Clone() cp.TLS = cfg.TLS.Clone()
} }
if len(cp.Params) > 0 { if len(cp.Params) > 0 {
cp.Params = make(map[string]string, len(cfg.Params)) cp.Params = make(map[string]string, len(cfg.Params))
@ -119,24 +120,29 @@ func (cfg *Config) normalize() error {
cfg.Addr = ensureHavePort(cfg.Addr) cfg.Addr = ensureHavePort(cfg.Addr)
} }
switch cfg.TLSConfig { if cfg.TLS == nil {
case "false", "": switch cfg.TLSConfig {
// don't set anything case "false", "":
case "true": // don't set anything
cfg.tls = &tls.Config{} case "true":
case "skip-verify", "preferred": cfg.TLS = &tls.Config{}
cfg.tls = &tls.Config{InsecureSkipVerify: true} case "skip-verify":
default: cfg.TLS = &tls.Config{InsecureSkipVerify: true}
cfg.tls = getTLSConfigClone(cfg.TLSConfig) case "preferred":
if cfg.tls == nil { cfg.TLS = &tls.Config{InsecureSkipVerify: true}
return errors.New("invalid value / unknown config name: " + cfg.TLSConfig) cfg.AllowFallbackToPlaintext = true
default:
cfg.TLS = getTLSConfigClone(cfg.TLSConfig)
if cfg.TLS == nil {
return errors.New("invalid value / unknown config name: " + cfg.TLSConfig)
}
} }
} }
if cfg.tls != nil && cfg.tls.ServerName == "" && !cfg.tls.InsecureSkipVerify { if cfg.TLS != nil && cfg.TLS.ServerName == "" && !cfg.TLS.InsecureSkipVerify {
host, _, err := net.SplitHostPort(cfg.Addr) host, _, err := net.SplitHostPort(cfg.Addr)
if err == nil { if err == nil {
cfg.tls.ServerName = host cfg.TLS.ServerName = host
} }
} }
@ -204,6 +210,10 @@ func (cfg *Config) FormatDSN() string {
writeDSNParam(&buf, &hasParam, "allowCleartextPasswords", "true") writeDSNParam(&buf, &hasParam, "allowCleartextPasswords", "true")
} }
if cfg.AllowFallbackToPlaintext {
writeDSNParam(&buf, &hasParam, "allowFallbackToPlaintext", "true")
}
if !cfg.AllowNativePasswords { if !cfg.AllowNativePasswords {
writeDSNParam(&buf, &hasParam, "allowNativePasswords", "false") writeDSNParam(&buf, &hasParam, "allowNativePasswords", "false")
} }
@ -391,6 +401,14 @@ func parseDSNParams(cfg *Config, params string) (err error) {
return errors.New("invalid bool value: " + value) return errors.New("invalid bool value: " + value)
} }
// Allow fallback to unencrypted connection if server does not support TLS
case "allowFallbackToPlaintext":
var isBool bool
cfg.AllowFallbackToPlaintext, isBool = readBool(value)
if !isBool {
return errors.New("invalid bool value: " + value)
}
// Use native password authentication // Use native password authentication
case "allowNativePasswords": case "allowNativePasswords":
var isBool bool var isBool bool
@ -426,7 +444,6 @@ func parseDSNParams(cfg *Config, params string) (err error) {
// Collation // Collation
case "collation": case "collation":
cfg.Collation = value cfg.Collation = value
break
case "columnsWithAlias": case "columnsWithAlias":
var isBool bool var isBool bool

View File

@ -56,10 +56,22 @@ func SetLogger(logger Logger) error {
// MySQLError is an error type which represents a single MySQL error // MySQLError is an error type which represents a single MySQL error
type MySQLError struct { type MySQLError struct {
Number uint16 Number uint16
Message string SQLState [5]byte
Message string
} }
func (me *MySQLError) Error() string { func (me *MySQLError) Error() string {
if me.SQLState != [5]byte{} {
return fmt.Sprintf("Error %d (%s): %s", me.Number, me.SQLState, me.Message)
}
return fmt.Sprintf("Error %d: %s", me.Number, me.Message) return fmt.Sprintf("Error %d: %s", me.Number, me.Message)
} }
func (me *MySQLError) Is(err error) bool {
if merr, ok := err.(*MySQLError); ok {
return merr.Number == me.Number
}
return false
}

View File

@ -41,6 +41,9 @@ func (mf *mysqlField) typeDatabaseName() string {
case fieldTypeJSON: case fieldTypeJSON:
return "JSON" return "JSON"
case fieldTypeLong: case fieldTypeLong:
if mf.flags&flagUnsigned != 0 {
return "UNSIGNED INT"
}
return "INT" return "INT"
case fieldTypeLongBLOB: case fieldTypeLongBLOB:
if mf.charSet != collations[binaryCollation] { if mf.charSet != collations[binaryCollation] {
@ -48,6 +51,9 @@ func (mf *mysqlField) typeDatabaseName() string {
} }
return "LONGBLOB" return "LONGBLOB"
case fieldTypeLongLong: case fieldTypeLongLong:
if mf.flags&flagUnsigned != 0 {
return "UNSIGNED BIGINT"
}
return "BIGINT" return "BIGINT"
case fieldTypeMediumBLOB: case fieldTypeMediumBLOB:
if mf.charSet != collations[binaryCollation] { if mf.charSet != collations[binaryCollation] {
@ -63,6 +69,9 @@ func (mf *mysqlField) typeDatabaseName() string {
case fieldTypeSet: case fieldTypeSet:
return "SET" return "SET"
case fieldTypeShort: case fieldTypeShort:
if mf.flags&flagUnsigned != 0 {
return "UNSIGNED SMALLINT"
}
return "SMALLINT" return "SMALLINT"
case fieldTypeString: case fieldTypeString:
if mf.charSet == collations[binaryCollation] { if mf.charSet == collations[binaryCollation] {
@ -74,6 +83,9 @@ func (mf *mysqlField) typeDatabaseName() string {
case fieldTypeTimestamp: case fieldTypeTimestamp:
return "TIMESTAMP" return "TIMESTAMP"
case fieldTypeTiny: case fieldTypeTiny:
if mf.flags&flagUnsigned != 0 {
return "UNSIGNED TINYINT"
}
return "TINYINT" return "TINYINT"
case fieldTypeTinyBLOB: case fieldTypeTinyBLOB:
if mf.charSet != collations[binaryCollation] { if mf.charSet != collations[binaryCollation] {
@ -106,7 +118,7 @@ var (
scanTypeInt64 = reflect.TypeOf(int64(0)) scanTypeInt64 = reflect.TypeOf(int64(0))
scanTypeNullFloat = reflect.TypeOf(sql.NullFloat64{}) scanTypeNullFloat = reflect.TypeOf(sql.NullFloat64{})
scanTypeNullInt = reflect.TypeOf(sql.NullInt64{}) scanTypeNullInt = reflect.TypeOf(sql.NullInt64{})
scanTypeNullTime = reflect.TypeOf(nullTime{}) scanTypeNullTime = reflect.TypeOf(sql.NullTime{})
scanTypeUint8 = reflect.TypeOf(uint8(0)) scanTypeUint8 = reflect.TypeOf(uint8(0))
scanTypeUint16 = reflect.TypeOf(uint16(0)) scanTypeUint16 = reflect.TypeOf(uint16(0))
scanTypeUint32 = reflect.TypeOf(uint32(0)) scanTypeUint32 = reflect.TypeOf(uint32(0))

View File

@ -6,6 +6,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this file, // License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/. // You can obtain one at http://mozilla.org/MPL/2.0/.
//go:build gofuzz
// +build gofuzz // +build gofuzz
package mysql package mysql

View File

@ -28,12 +28,11 @@ var (
// Alternatively you can allow the use of all local files with // Alternatively you can allow the use of all local files with
// the DSN parameter 'allowAllFiles=true' // the DSN parameter 'allowAllFiles=true'
// //
// filePath := "/home/gopher/data.csv" // filePath := "/home/gopher/data.csv"
// mysql.RegisterLocalFile(filePath) // mysql.RegisterLocalFile(filePath)
// err := db.Exec("LOAD DATA LOCAL INFILE '" + filePath + "' INTO TABLE foo") // err := db.Exec("LOAD DATA LOCAL INFILE '" + filePath + "' INTO TABLE foo")
// if err != nil { // if err != nil {
// ... // ...
//
func RegisterLocalFile(filePath string) { func RegisterLocalFile(filePath string) {
fileRegisterLock.Lock() fileRegisterLock.Lock()
// lazy map init // lazy map init
@ -58,15 +57,14 @@ func DeregisterLocalFile(filePath string) {
// If the handler returns a io.ReadCloser Close() is called when the // If the handler returns a io.ReadCloser Close() is called when the
// request is finished. // request is finished.
// //
// mysql.RegisterReaderHandler("data", func() io.Reader { // mysql.RegisterReaderHandler("data", func() io.Reader {
// var csvReader io.Reader // Some Reader that returns CSV data // var csvReader io.Reader // Some Reader that returns CSV data
// ... // Open Reader here // ... // Open Reader here
// return csvReader // return csvReader
// }) // })
// err := db.Exec("LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE foo") // err := db.Exec("LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE foo")
// if err != nil { // if err != nil {
// ... // ...
//
func RegisterReaderHandler(name string, handler func() io.Reader) { func RegisterReaderHandler(name string, handler func() io.Reader) {
readerRegisterLock.Lock() readerRegisterLock.Lock()
// lazy map init // lazy map init
@ -93,10 +91,12 @@ func deferredClose(err *error, closer io.Closer) {
} }
} }
const defaultPacketSize = 16 * 1024 // 16KB is small enough for disk readahead and large enough for TCP
func (mc *mysqlConn) handleInFileRequest(name string) (err error) { func (mc *mysqlConn) handleInFileRequest(name string) (err error) {
var rdr io.Reader var rdr io.Reader
var data []byte var data []byte
packetSize := 16 * 1024 // 16KB is small enough for disk readahead and large enough for TCP packetSize := defaultPacketSize
if mc.maxWriteSize < packetSize { if mc.maxWriteSize < packetSize {
packetSize = mc.maxWriteSize packetSize = mc.maxWriteSize
} }

View File

@ -9,11 +9,32 @@
package mysql package mysql
import ( import (
"database/sql"
"database/sql/driver" "database/sql/driver"
"fmt" "fmt"
"time" "time"
) )
// NullTime represents a time.Time that may be NULL.
// NullTime implements the Scanner interface so
// it can be used as a scan destination:
//
// var nt NullTime
// err := db.QueryRow("SELECT time FROM foo WHERE id=?", id).Scan(&nt)
// ...
// if nt.Valid {
// // use nt.Time
// } else {
// // NULL value
// }
//
// # This NullTime implementation is not driver-specific
//
// Deprecated: NullTime doesn't honor the loc DSN parameter.
// NullTime.Scan interprets a time as UTC, not the loc DSN parameter.
// Use sql.NullTime instead.
type NullTime sql.NullTime
// Scan implements the Scanner interface. // Scan implements the Scanner interface.
// The value type must be time.Time or string / []byte (formatted time-string), // The value type must be time.Time or string / []byte (formatted time-string),
// otherwise Scan fails. // otherwise Scan fails.

View File

@ -1,40 +0,0 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build go1.13
package mysql
import (
"database/sql"
)
// NullTime represents a time.Time that may be NULL.
// NullTime implements the Scanner interface so
// it can be used as a scan destination:
//
// var nt NullTime
// err := db.QueryRow("SELECT time FROM foo WHERE id=?", id).Scan(&nt)
// ...
// if nt.Valid {
// // use nt.Time
// } else {
// // NULL value
// }
//
// This NullTime implementation is not driver-specific
//
// Deprecated: NullTime doesn't honor the loc DSN parameter.
// NullTime.Scan interprets a time as UTC, not the loc DSN parameter.
// Use sql.NullTime instead.
type NullTime sql.NullTime
// for internal use.
// the mysql package uses sql.NullTime if it is available.
// if not, the package uses mysql.NullTime.
type nullTime = sql.NullTime // sql.NullTime is available

View File

@ -1,39 +0,0 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build !go1.13
package mysql
import (
"time"
)
// NullTime represents a time.Time that may be NULL.
// NullTime implements the Scanner interface so
// it can be used as a scan destination:
//
// var nt NullTime
// err := db.QueryRow("SELECT time FROM foo WHERE id=?", id).Scan(&nt)
// ...
// if nt.Valid {
// // use nt.Time
// } else {
// // NULL value
// }
//
// This NullTime implementation is not driver-specific
type NullTime struct {
Time time.Time
Valid bool // Valid is true if Time is not NULL
}
// for internal use.
// the mysql package uses sql.NullTime if it is available.
// if not, the package uses mysql.NullTime.
type nullTime = NullTime // sql.NullTime is not available

View File

@ -110,14 +110,13 @@ func (mc *mysqlConn) writePacket(data []byte) error {
conn = mc.rawConn conn = mc.rawConn
} }
var err error var err error
// If this connection has a ReadTimeout which we've been setting on if mc.cfg.CheckConnLiveness {
// reads, reset it to its default value before we attempt a non-blocking if mc.cfg.ReadTimeout != 0 {
// read, otherwise the scheduler will just time us out before we can read err = conn.SetReadDeadline(time.Now().Add(mc.cfg.ReadTimeout))
if mc.cfg.ReadTimeout != 0 { }
err = conn.SetReadDeadline(time.Time{}) if err == nil {
} err = connCheck(conn)
if err == nil && mc.cfg.CheckConnLiveness { }
err = connCheck(conn)
} }
if err != nil { if err != nil {
errLog.Print("closing bad idle connection: ", err) errLog.Print("closing bad idle connection: ", err)
@ -223,9 +222,9 @@ func (mc *mysqlConn) readHandshakePacket() (data []byte, plugin string, err erro
if mc.flags&clientProtocol41 == 0 { if mc.flags&clientProtocol41 == 0 {
return nil, "", ErrOldProtocol return nil, "", ErrOldProtocol
} }
if mc.flags&clientSSL == 0 && mc.cfg.tls != nil { if mc.flags&clientSSL == 0 && mc.cfg.TLS != nil {
if mc.cfg.TLSConfig == "preferred" { if mc.cfg.AllowFallbackToPlaintext {
mc.cfg.tls = nil mc.cfg.TLS = nil
} else { } else {
return nil, "", ErrNoTLS return nil, "", ErrNoTLS
} }
@ -293,7 +292,7 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string
} }
// To enable TLS / SSL // To enable TLS / SSL
if mc.cfg.tls != nil { if mc.cfg.TLS != nil {
clientFlags |= clientSSL clientFlags |= clientSSL
} }
@ -357,14 +356,14 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string
// SSL Connection Request Packet // SSL Connection Request Packet
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::SSLRequest // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::SSLRequest
if mc.cfg.tls != nil { if mc.cfg.TLS != nil {
// Send TLS / SSL request packet // Send TLS / SSL request packet
if err := mc.writePacket(data[:(4+4+1+23)+4]); err != nil { if err := mc.writePacket(data[:(4+4+1+23)+4]); err != nil {
return err return err
} }
// Switch to TLS // Switch to TLS
tlsConn := tls.Client(mc.netConn, mc.cfg.tls) tlsConn := tls.Client(mc.netConn, mc.cfg.TLS)
if err := tlsConn.Handshake(); err != nil { if err := tlsConn.Handshake(); err != nil {
return err return err
} }
@ -588,19 +587,20 @@ func (mc *mysqlConn) handleErrorPacket(data []byte) error {
return driver.ErrBadConn return driver.ErrBadConn
} }
me := &MySQLError{Number: errno}
pos := 3 pos := 3
// SQL State [optional: # + 5bytes string] // SQL State [optional: # + 5bytes string]
if data[3] == 0x23 { if data[3] == 0x23 {
//sqlstate := string(data[4 : 4+5]) copy(me.SQLState[:], data[4:4+5])
pos = 9 pos = 9
} }
// Error Message [string] // Error Message [string]
return &MySQLError{ me.Message = string(data[pos:])
Number: errno,
Message: string(data[pos:]), return me
}
} }
func readStatus(b []byte) statusFlag { func readStatus(b []byte) statusFlag {
@ -761,40 +761,40 @@ func (rows *textRows) readRow(dest []driver.Value) error {
} }
// RowSet Packet // RowSet Packet
var n int var (
var isNull bool n int
pos := 0 isNull bool
pos int = 0
)
for i := range dest { for i := range dest {
// Read bytes and convert to string // Read bytes and convert to string
dest[i], isNull, n, err = readLengthEncodedString(data[pos:]) dest[i], isNull, n, err = readLengthEncodedString(data[pos:])
pos += n pos += n
if err == nil {
if !isNull {
if !mc.parseTime {
continue
} else {
switch rows.rs.columns[i].fieldType {
case fieldTypeTimestamp, fieldTypeDateTime,
fieldTypeDate, fieldTypeNewDate:
dest[i], err = parseDateTime(
dest[i].([]byte),
mc.cfg.Loc,
)
if err == nil {
continue
}
default:
continue
}
}
} else { if err != nil {
dest[i] = nil return err
continue }
if isNull {
dest[i] = nil
continue
}
if !mc.parseTime {
continue
}
// Parse time field
switch rows.rs.columns[i].fieldType {
case fieldTypeTimestamp,
fieldTypeDateTime,
fieldTypeDate,
fieldTypeNewDate:
if dest[i], err = parseDateTime(dest[i].([]byte), mc.cfg.Loc); err != nil {
return err
} }
} }
return err // err != nil
} }
return nil return nil

View File

@ -23,7 +23,7 @@ type mysqlStmt struct {
} }
func (stmt *mysqlStmt) Close() error { func (stmt *mysqlStmt) Close() error {
if stmt.mc == nil || stmt.mc.closed.IsSet() { if stmt.mc == nil || stmt.mc.closed.Load() {
// driver.Stmt.Close can be called more than once, thus this function // driver.Stmt.Close can be called more than once, thus this function
// has to be idempotent. // has to be idempotent.
// See also Issue #450 and golang/go#16019. // See also Issue #450 and golang/go#16019.
@ -50,7 +50,7 @@ func (stmt *mysqlStmt) CheckNamedValue(nv *driver.NamedValue) (err error) {
} }
func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) { func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) {
if stmt.mc.closed.IsSet() { if stmt.mc.closed.Load() {
errLog.Print(ErrInvalidConn) errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn return nil, driver.ErrBadConn
} }
@ -98,7 +98,7 @@ func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
} }
func (stmt *mysqlStmt) query(args []driver.Value) (*binaryRows, error) { func (stmt *mysqlStmt) query(args []driver.Value) (*binaryRows, error) {
if stmt.mc.closed.IsSet() { if stmt.mc.closed.Load() {
errLog.Print(ErrInvalidConn) errLog.Print(ErrInvalidConn)
return nil, driver.ErrBadConn return nil, driver.ErrBadConn
} }
@ -157,7 +157,7 @@ func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
if driver.IsValue(sv) { if driver.IsValue(sv) {
return sv, nil return sv, nil
} }
// A value returend from the Valuer interface can be "a type handled by // A value returned from the Valuer interface can be "a type handled by
// a database driver's NamedValueChecker interface" so we should accept // a database driver's NamedValueChecker interface" so we should accept
// uint64 here as well. // uint64 here as well.
if u, ok := sv.(uint64); ok { if u, ok := sv.(uint64); ok {

View File

@ -13,7 +13,7 @@ type mysqlTx struct {
} }
func (tx *mysqlTx) Commit() (err error) { func (tx *mysqlTx) Commit() (err error) {
if tx.mc == nil || tx.mc.closed.IsSet() { if tx.mc == nil || tx.mc.closed.Load() {
return ErrInvalidConn return ErrInvalidConn
} }
err = tx.mc.exec("COMMIT") err = tx.mc.exec("COMMIT")
@ -22,7 +22,7 @@ func (tx *mysqlTx) Commit() (err error) {
} }
func (tx *mysqlTx) Rollback() (err error) { func (tx *mysqlTx) Rollback() (err error) {
if tx.mc == nil || tx.mc.closed.IsSet() { if tx.mc == nil || tx.mc.closed.Load() {
return ErrInvalidConn return ErrInvalidConn
} }
err = tx.mc.exec("ROLLBACK") err = tx.mc.exec("ROLLBACK")

View File

@ -35,26 +35,25 @@ var (
// Note: The provided tls.Config is exclusively owned by the driver after // Note: The provided tls.Config is exclusively owned by the driver after
// registering it. // registering it.
// //
// rootCertPool := x509.NewCertPool() // rootCertPool := x509.NewCertPool()
// pem, err := ioutil.ReadFile("/path/ca-cert.pem") // pem, err := ioutil.ReadFile("/path/ca-cert.pem")
// if err != nil { // if err != nil {
// log.Fatal(err) // log.Fatal(err)
// } // }
// if ok := rootCertPool.AppendCertsFromPEM(pem); !ok { // if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
// log.Fatal("Failed to append PEM.") // log.Fatal("Failed to append PEM.")
// } // }
// clientCert := make([]tls.Certificate, 0, 1) // clientCert := make([]tls.Certificate, 0, 1)
// certs, err := tls.LoadX509KeyPair("/path/client-cert.pem", "/path/client-key.pem") // certs, err := tls.LoadX509KeyPair("/path/client-cert.pem", "/path/client-key.pem")
// if err != nil { // if err != nil {
// log.Fatal(err) // log.Fatal(err)
// } // }
// clientCert = append(clientCert, certs) // clientCert = append(clientCert, certs)
// mysql.RegisterTLSConfig("custom", &tls.Config{ // mysql.RegisterTLSConfig("custom", &tls.Config{
// RootCAs: rootCertPool, // RootCAs: rootCertPool,
// Certificates: clientCert, // Certificates: clientCert,
// }) // })
// db, err := sql.Open("mysql", "user@tcp(localhost:3306)/test?tls=custom") // db, err := sql.Open("mysql", "user@tcp(localhost:3306)/test?tls=custom")
//
func RegisterTLSConfig(key string, config *tls.Config) error { func RegisterTLSConfig(key string, config *tls.Config) error {
if _, isBool := readBool(key); isBool || strings.ToLower(key) == "skip-verify" || strings.ToLower(key) == "preferred" { if _, isBool := readBool(key); isBool || strings.ToLower(key) == "skip-verify" || strings.ToLower(key) == "preferred" {
return fmt.Errorf("key '%s' is reserved", key) return fmt.Errorf("key '%s' is reserved", key)
@ -118,10 +117,6 @@ func parseDateTime(b []byte, loc *time.Location) (time.Time, error) {
if err != nil { if err != nil {
return time.Time{}, err return time.Time{}, err
} }
if year <= 0 {
year = 1
}
if b[4] != '-' { if b[4] != '-' {
return time.Time{}, fmt.Errorf("bad value for field: `%c`", b[4]) return time.Time{}, fmt.Errorf("bad value for field: `%c`", b[4])
} }
@ -130,9 +125,6 @@ func parseDateTime(b []byte, loc *time.Location) (time.Time, error) {
if err != nil { if err != nil {
return time.Time{}, err return time.Time{}, err
} }
if m <= 0 {
m = 1
}
month := time.Month(m) month := time.Month(m)
if b[7] != '-' { if b[7] != '-' {
@ -143,9 +135,6 @@ func parseDateTime(b []byte, loc *time.Location) (time.Time, error) {
if err != nil { if err != nil {
return time.Time{}, err return time.Time{}, err
} }
if day <= 0 {
day = 1
}
if len(b) == 10 { if len(b) == 10 {
return time.Date(year, month, day, 0, 0, 0, 0, loc), nil return time.Date(year, month, day, 0, 0, 0, 0, loc), nil
} }
@ -199,7 +188,7 @@ func parseByteYear(b []byte) (int, error) {
return 0, err return 0, err
} }
year += v * n year += v * n
n = n / 10 n /= 10
} }
return year, nil return year, nil
} }
@ -542,7 +531,7 @@ func stringToInt(b []byte) int {
return val return val
} }
// returns the string read as a bytes slice, wheter the value is NULL, // returns the string read as a bytes slice, whether the value is NULL,
// the number of bytes read and an error, in case the string is longer than // the number of bytes read and an error, in case the string is longer than
// the input slice // the input slice
func readLengthEncodedString(b []byte) ([]byte, bool, int, error) { func readLengthEncodedString(b []byte) ([]byte, bool, int, error) {
@ -652,32 +641,32 @@ func escapeBytesBackslash(buf, v []byte) []byte {
for _, c := range v { for _, c := range v {
switch c { switch c {
case '\x00': case '\x00':
buf[pos] = '\\'
buf[pos+1] = '0' buf[pos+1] = '0'
buf[pos] = '\\'
pos += 2 pos += 2
case '\n': case '\n':
buf[pos] = '\\'
buf[pos+1] = 'n' buf[pos+1] = 'n'
buf[pos] = '\\'
pos += 2 pos += 2
case '\r': case '\r':
buf[pos] = '\\'
buf[pos+1] = 'r' buf[pos+1] = 'r'
buf[pos] = '\\'
pos += 2 pos += 2
case '\x1a': case '\x1a':
buf[pos] = '\\'
buf[pos+1] = 'Z' buf[pos+1] = 'Z'
buf[pos] = '\\'
pos += 2 pos += 2
case '\'': case '\'':
buf[pos] = '\\'
buf[pos+1] = '\'' buf[pos+1] = '\''
buf[pos] = '\\'
pos += 2 pos += 2
case '"': case '"':
buf[pos] = '\\'
buf[pos+1] = '"' buf[pos+1] = '"'
buf[pos] = '\\'
pos += 2 pos += 2
case '\\': case '\\':
buf[pos] = '\\'
buf[pos+1] = '\\' buf[pos+1] = '\\'
buf[pos] = '\\'
pos += 2 pos += 2
default: default:
buf[pos] = c buf[pos] = c
@ -697,32 +686,32 @@ func escapeStringBackslash(buf []byte, v string) []byte {
c := v[i] c := v[i]
switch c { switch c {
case '\x00': case '\x00':
buf[pos] = '\\'
buf[pos+1] = '0' buf[pos+1] = '0'
buf[pos] = '\\'
pos += 2 pos += 2
case '\n': case '\n':
buf[pos] = '\\'
buf[pos+1] = 'n' buf[pos+1] = 'n'
buf[pos] = '\\'
pos += 2 pos += 2
case '\r': case '\r':
buf[pos] = '\\'
buf[pos+1] = 'r' buf[pos+1] = 'r'
buf[pos] = '\\'
pos += 2 pos += 2
case '\x1a': case '\x1a':
buf[pos] = '\\'
buf[pos+1] = 'Z' buf[pos+1] = 'Z'
buf[pos] = '\\'
pos += 2 pos += 2
case '\'': case '\'':
buf[pos] = '\\'
buf[pos+1] = '\'' buf[pos+1] = '\''
buf[pos] = '\\'
pos += 2 pos += 2
case '"': case '"':
buf[pos] = '\\'
buf[pos+1] = '"' buf[pos+1] = '"'
buf[pos] = '\\'
pos += 2 pos += 2
case '\\': case '\\':
buf[pos] = '\\'
buf[pos+1] = '\\' buf[pos+1] = '\\'
buf[pos] = '\\'
pos += 2 pos += 2
default: default:
buf[pos] = c buf[pos] = c
@ -744,8 +733,8 @@ func escapeBytesQuotes(buf, v []byte) []byte {
for _, c := range v { for _, c := range v {
if c == '\'' { if c == '\'' {
buf[pos] = '\''
buf[pos+1] = '\'' buf[pos+1] = '\''
buf[pos] = '\''
pos += 2 pos += 2
} else { } else {
buf[pos] = c buf[pos] = c
@ -764,8 +753,8 @@ func escapeStringQuotes(buf []byte, v string) []byte {
for i := 0; i < len(v); i++ { for i := 0; i < len(v); i++ {
c := v[i] c := v[i]
if c == '\'' { if c == '\'' {
buf[pos] = '\''
buf[pos+1] = '\'' buf[pos+1] = '\''
buf[pos] = '\''
pos += 2 pos += 2
} else { } else {
buf[pos] = c buf[pos] = c
@ -790,39 +779,16 @@ type noCopy struct{}
// Lock is a no-op used by -copylocks checker from `go vet`. // Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) Lock() {} func (*noCopy) Lock() {}
// atomicBool is a wrapper around uint32 for usage as a boolean value with // Unlock is a no-op used by -copylocks checker from `go vet`.
// atomic access. // noCopy should implement sync.Locker from Go 1.11
type atomicBool struct { // https://github.com/golang/go/commit/c2eba53e7f80df21d51285879d51ab81bcfbf6bc
_noCopy noCopy // https://github.com/golang/go/issues/26165
value uint32 func (*noCopy) Unlock() {}
}
// IsSet returns whether the current boolean value is true
func (ab *atomicBool) IsSet() bool {
return atomic.LoadUint32(&ab.value) > 0
}
// Set sets the value of the bool regardless of the previous value
func (ab *atomicBool) Set(value bool) {
if value {
atomic.StoreUint32(&ab.value, 1)
} else {
atomic.StoreUint32(&ab.value, 0)
}
}
// TrySet sets the value of the bool and returns whether the value changed
func (ab *atomicBool) TrySet(value bool) bool {
if value {
return atomic.SwapUint32(&ab.value, 1) == 0
}
return atomic.SwapUint32(&ab.value, 0) > 0
}
// atomicError is a wrapper for atomically accessed error values // atomicError is a wrapper for atomically accessed error values
type atomicError struct { type atomicError struct {
_noCopy noCopy _ noCopy
value atomic.Value value atomic.Value
} }
// Set sets the error value regardless of the previous value. // Set sets the error value regardless of the previous value.

View File

@ -2,26 +2,351 @@
[![GoDoc](https://godoc.org/github.com/tidwall/btree?status.svg)](https://godoc.org/github.com/tidwall/btree) [![GoDoc](https://godoc.org/github.com/tidwall/btree?status.svg)](https://godoc.org/github.com/tidwall/btree)
An [efficient](#performance) [B-tree](https://en.wikipedia.org/wiki/B-tree) implementation in Go. An efficient [B-tree](https://en.wikipedia.org/wiki/B-tree) implementation in Go.
*Check out the [generics branch](https://github.com/tidwall/btree/tree/generics) if you want to try out btree with generic support for Go 1.18+*
## Features ## Features
- `Copy()` method with copy-on-write support. - Support for [Generics](#generics) (Go 1.18+).
- `Map` and `Set` types for ordered key-value maps and sets,
- Fast bulk loading for pre-ordered data using the `Load()` method. - Fast bulk loading for pre-ordered data using the `Load()` method.
- All operations are thread-safe. - `Copy()` method with copy-on-write support.
- Thread-safe operations.
- [Path hinting](PATH_HINT.md) optimization for operations with nearby keys. - [Path hinting](PATH_HINT.md) optimization for operations with nearby keys.
## Installing ## Using
To start using btree, install Go and run `go get`: To start using this package, install Go and run:
```sh ```sh
$ go get -u github.com/tidwall/btree $ go get github.com/tidwall/btree
``` ```
## Usage ## B-tree types
This package includes the following types of B-trees:
- [`btree.Map`](#btreemap):
A fast B-tree for storing ordered key value pairs.
Go 1.18+
- [`btree.Set`](#btreeset):
Like `Map`, but only for storing keys.
Go 1.18+
- [`btree.BTreeG`](#btreegeneric):
A feature-rich B-tree for storing data using a custom comparator.
Go 1.18+
- [`btree.BTree`](#btreebtree):
Like `BTreeG` but uses the `interface{}` type for data. Backwards compatible.
Go 1.16+
### btree.Map
```go
// Basic
Set(key, value) // insert or replace an item
Get(key, value) // get an existing item
Delete(key) // delete an item
Len() // return the number of items in the map
// Iteration
Scan(iter) // scan items in ascending order
Reverse(iter) // scan items in descending order
Ascend(key, iter) // scan items in ascending order that are >= to key
Descend(key, iter) // scan items in descending order that are <= to key.
Iter() // returns a read-only iterator for for-loops.
// Array-like operations
GetAt(index) // returns the item at index
DeleteAt(index) // deletes the item at index
// Bulk-loading
Load(key, value) // load presorted items into tree
```
#### Example
```go
package main
import (
"fmt"
"github.com/tidwall/btree"
)
func main() {
// create a map
var users btree.Map[string, string]
// add some users
users.Set("user:4", "Andrea")
users.Set("user:6", "Andy")
users.Set("user:2", "Andy")
users.Set("user:1", "Jane")
users.Set("user:5", "Janet")
users.Set("user:3", "Steve")
// Iterate over the maps and print each user
users.Scan(func(key, value string) bool {
fmt.Printf("%s %s\n", key, value)
return true
})
fmt.Printf("\n")
// Delete a couple
users.Delete("user:5")
users.Delete("user:1")
// print the map again
users.Scan(func(key, value string) bool {
fmt.Printf("%s %s\n", key, value)
return true
})
fmt.Printf("\n")
// Output:
// user:1 Jane
// user:2 Andy
// user:3 Steve
// user:4 Andrea
// user:5 Janet
// user:6 Andy
//
// user:2 Andy
// user:3 Steve
// user:4 Andrea
// user:6 Andy
}
```
### btree.Set
```go
// Basic
Insert(key) // insert an item
Contains(key) // test if item exists
Delete(key) // delete an item
Len() // return the number of items in the set
// Iteration
Scan(iter) // scan items in ascending order
Reverse(iter) // scan items in descending order
Ascend(key, iter) // scan items in ascending order that are >= to key
Descend(key, iter) // scan items in descending order that are <= to key.
Iter() // returns a read-only iterator for for-loops.
// Array-like operations
GetAt(index) // returns the item at index
DeleteAt(index) // deletes the item at index
// Bulk-loading
Load(key) // load presorted item into tree
```
#### Example
```go
package main
import (
"fmt"
"github.com/tidwall/btree"
)
func main() {
// create a set
var names btree.Set[string]
// add some names
names.Insert("Jane")
names.Insert("Andrea")
names.Insert("Steve")
names.Insert("Andy")
names.Insert("Janet")
names.Insert("Andy")
// Iterate over the maps and print each user
names.Scan(func(key string) bool {
fmt.Printf("%s\n", key)
return true
})
fmt.Printf("\n")
// Delete a couple
names.Delete("Steve")
names.Delete("Andy")
// print the map again
names.Scan(func(key string) bool {
fmt.Printf("%s\n", key)
return true
})
fmt.Printf("\n")
// Output:
// Andrea
// Andy
// Jane
// Janet
// Steve
//
// Andrea
// Jane
// Janet
}
```
### btree.BTreeG
```go
// Basic
Set(item) // insert or replace an item
Get(item) // get an existing item
Delete(item) // delete an item
Len() // return the number of items in the btree
// Iteration
Scan(iter) // scan items in ascending order
Reverse(iter) // scan items in descending order
Ascend(key, iter) // scan items in ascending order that are >= to key
Descend(key, iter) // scan items in descending order that are <= to key.
Iter() // returns a read-only iterator for for-loops.
// Array-like operations
GetAt(index) // returns the item at index
DeleteAt(index) // deletes the item at index
// Bulk-loading
Load(item) // load presorted items into tree
// Path hinting
SetHint(item, *hint) // insert or replace an existing item
GetHint(item, *hint) // get an existing item
DeleteHint(item, *hint) // delete an item
// Copy-on-write
Copy() // copy the btree
```
#### Example
```go
package main
import (
"fmt"
"github.com/tidwall/btree"
)
type Item struct {
Key, Val string
}
// byKeys is a comparison function that compares item keys and returns true
// when a is less than b.
func byKeys(a, b Item) bool {
return a.Key < b.Key
}
// byVals is a comparison function that compares item values and returns true
// when a is less than b.
func byVals(a, b Item) bool {
if a.Val < b.Val {
return true
}
if a.Val > b.Val {
return false
}
// Both vals are equal so we should fall though
// and let the key comparison take over.
return byKeys(a, b)
}
func main() {
// Create a tree for keys and a tree for values.
// The "keys" tree will be sorted on the Keys field.
// The "values" tree will be sorted on the Values field.
keys := btree.NewBTreeG[Item](byKeys)
vals := btree.NewBTreeG[Item](byVals)
// Create some items.
users := []Item{
Item{Key: "user:1", Val: "Jane"},
Item{Key: "user:2", Val: "Andy"},
Item{Key: "user:3", Val: "Steve"},
Item{Key: "user:4", Val: "Andrea"},
Item{Key: "user:5", Val: "Janet"},
Item{Key: "user:6", Val: "Andy"},
}
// Insert each user into both trees
for _, user := range users {
keys.Set(user)
vals.Set(user)
}
// Iterate over each user in the key tree
keys.Scan(func(item Item) bool {
fmt.Printf("%s %s\n", item.Key, item.Val)
return true
})
fmt.Printf("\n")
// Iterate over each user in the val tree
vals.Scan(func(item Item) bool {
fmt.Printf("%s %s\n", item.Key, item.Val)
return true
})
// Output:
// user:1 Jane
// user:2 Andy
// user:3 Steve
// user:4 Andrea
// user:5 Janet
// user:6 Andy
//
// user:4 Andrea
// user:2 Andy
// user:6 Andy
// user:1 Jane
// user:5 Janet
// user:3 Steve
}
```
### btree.BTree
```go
// Basic
Set(item) // insert or replace an item
Get(item) // get an existing item
Delete(item) // delete an item
Len() // return the number of items in the btree
// Iteration
Scan(iter) // scan items in ascending order
Reverse(iter) // scan items in descending order
Ascend(key, iter) // scan items in ascending order that are >= to key
Descend(key, iter) // scan items in descending order that are <= to key.
Iter() // returns a read-only iterator for for-loops.
// Array-like operations
GetAt(index) // returns the item at index
DeleteAt(index) // deletes the item at index
// Bulk-loading
Load(item) // load presorted items into tree
// Path hinting
SetHint(item, *hint) // insert or replace an existing item
GetHint(item, *hint) // get an existing item
DeleteHint(item, *hint) // delete an item
// Copy-on-write
Copy() // copy the btree
```
#### Example
```go ```go
package main package main
@ -113,92 +438,9 @@ func main() {
} }
``` ```
## Operations
### Basic
```
Get(item) # get an existing item
Set(item) # insert or replace an existing item
Delete(item) # delete an item
Len() # return the number of items in the btree
```
### Iteration
```
Ascend(pivot, iter) # scan items in ascending order starting at pivot.
Descend(pivot, iter) # scan items in descending order starting at pivot.
Iter() # returns a read-only iterator for for-loops.
```
### Queues
```
Min() # return the first item in the btree
Max() # return the last item in the btree
PopMin() # remove and return the first item in the btree
PopMax() # remove and return the last item in the btree
```
### Bulk loading
```
Load(item) # load presorted items into tree
```
### Path hints
```
SetHint(item, *hint) # insert or replace an existing item
GetHint(item, *hint) # get an existing item
DeleteHint(item, *hint) # delete an item
```
### Array-like operations
```
GetAt(index) # returns the value at index
DeleteAt(index) # deletes the item at index
```
## Performance ## Performance
This implementation was designed with performance in mind. See [tidwall/btree-benchmark](https://github.com/tidwall/btree-benchmark) for benchmark numbers.
The following benchmarks were run on my 2019 Macbook Pro (2.4 GHz 8-Core Intel Core i9) using Go 1.17.3. The items are simple 8-byte ints.
- `google`: The [google/btree](https://github.com/google/btree) package
- `tidwall`: The [tidwall/btree](https://github.com/tidwall/btree) package
- `go-arr`: Just a simple Go array
```
** sequential set **
google: set-seq 1,000,000 ops in 178ms, 5,618,049/sec, 177 ns/op, 39.0 MB, 40 bytes/op
tidwall: set-seq 1,000,000 ops in 156ms, 6,389,837/sec, 156 ns/op, 23.5 MB, 24 bytes/op
tidwall: set-seq-hint 1,000,000 ops in 78ms, 12,895,355/sec, 77 ns/op, 23.5 MB, 24 bytes/op
tidwall: load-seq 1,000,000 ops in 53ms, 18,937,400/sec, 52 ns/op, 23.5 MB, 24 bytes/op
go-arr: append 1,000,000 ops in 78ms, 12,843,432/sec, 77 ns/op
** random set **
google: set-rand 1,000,000 ops in 555ms, 1,803,133/sec, 554 ns/op, 29.7 MB, 31 bytes/op
tidwall: set-rand 1,000,000 ops in 545ms, 1,835,818/sec, 544 ns/op, 29.6 MB, 31 bytes/op
tidwall: set-rand-hint 1,000,000 ops in 670ms, 1,493,473/sec, 669 ns/op, 29.6 MB, 31 bytes/op
tidwall: set-again 1,000,000 ops in 681ms, 1,469,038/sec, 680 ns/op
tidwall: set-after-copy 1,000,000 ops in 670ms, 1,493,230/sec, 669 ns/op
tidwall: load-rand 1,000,000 ops in 569ms, 1,756,187/sec, 569 ns/op, 29.6 MB, 31 bytes/op
** sequential get **
google: get-seq 1,000,000 ops in 165ms, 6,048,307/sec, 165 ns/op
tidwall: get-seq 1,000,000 ops in 144ms, 6,940,120/sec, 144 ns/op
tidwall: get-seq-hint 1,000,000 ops in 78ms, 12,815,243/sec, 78 ns/op
** random get **
google: get-rand 1,000,000 ops in 701ms, 1,427,507/sec, 700 ns/op
tidwall: get-rand 1,000,000 ops in 679ms, 1,473,531/sec, 678 ns/op
tidwall: get-rand-hint 1,000,000 ops in 824ms, 1,213,805/sec, 823 ns/op
```
*You can find the benchmark utility at [tidwall/btree-benchmark](https://github.com/tidwall/btree-benchmark)*
## Contact ## Contact

View File

@ -3,25 +3,17 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package btree package btree
import btree "github.com/tidwall/btree/internal"
type BTree struct { type BTree struct {
base *btree.BTree base *BTreeG[any]
} }
// PathHint is a utility type used with the *Hint() functions. Hints provide
// faster operations for clustered keys.
type PathHint = btree.PathHint
// New returns a new BTree // New returns a new BTree
func New(less func(a, b interface{}) bool) *BTree { func New(less func(a, b any) bool) *BTree {
if less == nil { if less == nil {
panic("nil less") panic("nil less")
} }
return &BTree{ return &BTree{
base: btree.NewOptions(btree.Options{ base: NewBTreeG(less),
Context: less,
}),
} }
} }
@ -30,31 +22,33 @@ func New(less func(a, b interface{}) bool) *BTree {
// //
// This is useful for when you do not need the BTree to manage the locking, // This is useful for when you do not need the BTree to manage the locking,
// but would rather do it yourself. // but would rather do it yourself.
func NewNonConcurrent(less func(a, b interface{}) bool) *BTree { func NewNonConcurrent(less func(a, b any) bool) *BTree {
if less == nil { if less == nil {
panic("nil less") panic("nil less")
} }
return &BTree{ return &BTree{
base: btree.NewOptions(btree.Options{ base: NewBTreeGOptions(less,
Context: less, Options{
NoLocks: true, NoLocks: true,
}), }),
} }
} }
// Less is a convenience function that performs a comparison of two items // Less is a convenience function that performs a comparison of two items
// using the same "less" function provided to New. // using the same "less" function provided to New.
func (tr *BTree) Less(a, b interface{}) bool { func (tr *BTree) Less(a, b any) bool {
return tr.base.Less(a, b) return tr.base.Less(a, b)
} }
// Set or replace a value for a key // Set or replace a value for a key
func (tr *BTree) Set(item interface{}) interface{} { // Returns the value for the replaced item or nil if the key was not found.
func (tr *BTree) Set(item any) (prev any) {
return tr.SetHint(item, nil) return tr.SetHint(item, nil)
} }
// SetHint sets or replace a value for a key using a path hint // SetHint sets or replace a value for a key using a path hint
func (tr *BTree) SetHint(item interface{}, hint *PathHint) (prev interface{}) { // Returns the value for the replaced item or nil if the key was not found.
func (tr *BTree) SetHint(item any, hint *PathHint) (prev any) {
if item == nil { if item == nil {
panic("nil item") panic("nil item")
} }
@ -65,13 +59,15 @@ func (tr *BTree) SetHint(item interface{}, hint *PathHint) (prev interface{}) {
return v return v
} }
// Get a value for key // Get a value for key.
func (tr *BTree) Get(key interface{}) interface{} { // Returns nil if the key was not found.
func (tr *BTree) Get(key any) any {
return tr.GetHint(key, nil) return tr.GetHint(key, nil)
} }
// GetHint gets a value for key using a path hint // GetHint gets a value for key using a path hint.
func (tr *BTree) GetHint(key interface{}, hint *PathHint) interface{} { // Returns nil if the item was not found.
func (tr *BTree) GetHint(key any, hint *PathHint) (value any) {
if key == nil { if key == nil {
return nil return nil
} }
@ -87,13 +83,15 @@ func (tr *BTree) Len() int {
return tr.base.Len() return tr.base.Len()
} }
// Delete a value for a key // Delete an item for a key.
func (tr *BTree) Delete(key interface{}) interface{} { // Returns the deleted value or nil if the key was not found.
func (tr *BTree) Delete(key any) (prev any) {
return tr.DeleteHint(key, nil) return tr.DeleteHint(key, nil)
} }
// DeleteHint deletes a value for a key using a path hint // DeleteHint deletes a value for a key using a path hint
func (tr *BTree) DeleteHint(key interface{}, hint *PathHint) interface{} { // Returns the deleted value or nil if the key was not found.
func (tr *BTree) DeleteHint(key any, hint *PathHint) (prev any) {
if key == nil { if key == nil {
return nil return nil
} }
@ -107,7 +105,7 @@ func (tr *BTree) DeleteHint(key interface{}, hint *PathHint) interface{} {
// Ascend the tree within the range [pivot, last] // Ascend the tree within the range [pivot, last]
// Pass nil for pivot to scan all item in ascending order // Pass nil for pivot to scan all item in ascending order
// Return false to stop iterating // Return false to stop iterating
func (tr *BTree) Ascend(pivot interface{}, iter func(item interface{}) bool) { func (tr *BTree) Ascend(pivot any, iter func(item any) bool) {
if pivot == nil { if pivot == nil {
tr.base.Scan(iter) tr.base.Scan(iter)
} else { } else {
@ -118,7 +116,7 @@ func (tr *BTree) Ascend(pivot interface{}, iter func(item interface{}) bool) {
// Descend the tree within the range [pivot, first] // Descend the tree within the range [pivot, first]
// Pass nil for pivot to scan all item in descending order // Pass nil for pivot to scan all item in descending order
// Return false to stop iterating // Return false to stop iterating
func (tr *BTree) Descend(pivot interface{}, iter func(item interface{}) bool) { func (tr *BTree) Descend(pivot any, iter func(item any) bool) {
if pivot == nil { if pivot == nil {
tr.base.Reverse(iter) tr.base.Reverse(iter)
} else { } else {
@ -127,7 +125,9 @@ func (tr *BTree) Descend(pivot interface{}, iter func(item interface{}) bool) {
} }
// Load is for bulk loading pre-sorted items // Load is for bulk loading pre-sorted items
func (tr *BTree) Load(item interface{}) interface{} { // If the load replaces and existing item then the value for the replaced item
// is returned.
func (tr *BTree) Load(item any) (prev any) {
if item == nil { if item == nil {
panic("nil item") panic("nil item")
} }
@ -140,7 +140,7 @@ func (tr *BTree) Load(item interface{}) interface{} {
// Min returns the minimum item in tree. // Min returns the minimum item in tree.
// Returns nil if the tree has no items. // Returns nil if the tree has no items.
func (tr *BTree) Min() interface{} { func (tr *BTree) Min() any {
v, ok := tr.base.Min() v, ok := tr.base.Min()
if !ok { if !ok {
return nil return nil
@ -150,7 +150,7 @@ func (tr *BTree) Min() interface{} {
// Max returns the maximum item in tree. // Max returns the maximum item in tree.
// Returns nil if the tree has no items. // Returns nil if the tree has no items.
func (tr *BTree) Max() interface{} { func (tr *BTree) Max() any {
v, ok := tr.base.Max() v, ok := tr.base.Max()
if !ok { if !ok {
return nil return nil
@ -160,7 +160,7 @@ func (tr *BTree) Max() interface{} {
// PopMin removes the minimum item in tree and returns it. // PopMin removes the minimum item in tree and returns it.
// Returns nil if the tree has no items. // Returns nil if the tree has no items.
func (tr *BTree) PopMin() interface{} { func (tr *BTree) PopMin() any {
v, ok := tr.base.PopMin() v, ok := tr.base.PopMin()
if !ok { if !ok {
return nil return nil
@ -168,9 +168,9 @@ func (tr *BTree) PopMin() interface{} {
return v return v
} }
// PopMax removes the minimum item in tree and returns it. // PopMax removes the maximum item in tree and returns it.
// Returns nil if the tree has no items. // Returns nil if the tree has no items.
func (tr *BTree) PopMax() interface{} { func (tr *BTree) PopMax() any {
v, ok := tr.base.PopMax() v, ok := tr.base.PopMax()
if !ok { if !ok {
return nil return nil
@ -180,7 +180,7 @@ func (tr *BTree) PopMax() interface{} {
// GetAt returns the value at index. // GetAt returns the value at index.
// Return nil if the tree is empty or the index is out of bounds. // Return nil if the tree is empty or the index is out of bounds.
func (tr *BTree) GetAt(index int) interface{} { func (tr *BTree) GetAt(index int) any {
v, ok := tr.base.GetAt(index) v, ok := tr.base.GetAt(index)
if !ok { if !ok {
return nil return nil
@ -190,7 +190,7 @@ func (tr *BTree) GetAt(index int) interface{} {
// DeleteAt deletes the item at index. // DeleteAt deletes the item at index.
// Return nil if the tree is empty or the index is out of bounds. // Return nil if the tree is empty or the index is out of bounds.
func (tr *BTree) DeleteAt(index int) interface{} { func (tr *BTree) DeleteAt(index int) any {
v, ok := tr.base.DeleteAt(index) v, ok := tr.base.DeleteAt(index)
if !ok { if !ok {
return nil return nil
@ -206,8 +206,8 @@ func (tr *BTree) Height() int {
// Walk iterates over all items in tree, in order. // Walk iterates over all items in tree, in order.
// The items param will contain one or more items. // The items param will contain one or more items.
func (tr *BTree) Walk(iter func(items []interface{})) { func (tr *BTree) Walk(iter func(items []any)) {
tr.base.Walk(func(items []interface{}) bool { tr.base.Walk(func(items []any) bool {
iter(items) iter(items)
return true return true
}) })
@ -220,7 +220,7 @@ func (tr *BTree) Copy() *BTree {
} }
type Iter struct { type Iter struct {
base btree.Iter base GenericIter[any]
} }
// Iter returns a read-only iterator. // Iter returns a read-only iterator.
@ -231,7 +231,7 @@ func (tr *BTree) Iter() Iter {
// Seek to item greater-or-equal-to key. // Seek to item greater-or-equal-to key.
// Returns false if there was no item found. // Returns false if there was no item found.
func (iter *Iter) Seek(key interface{}) bool { func (iter *Iter) Seek(key any) bool {
return iter.base.Seek(key) return iter.base.Seek(key)
} }
@ -268,6 +268,6 @@ func (iter *Iter) Prev() bool {
} }
// Item returns the current iterator item. // Item returns the current iterator item.
func (iter *Iter) Item() interface{} { func (iter *Iter) Item() any {
return iter.base.Item() return iter.base.Item()
} }

View File

@ -1,178 +1,109 @@
// Copyright 2020 Joshua J Baker. All rights reserved. // Copyright 2020 Joshua J Baker. All rights reserved.
// Use of this source code is governed by an MIT-style license that can be // Use of this source code is governed by an MIT-style
// found in the LICENSE file at https://github.com/tidwall/btree/LICENSE // license that can be found in the LICENSE file.
///////////////////////////////////////////////////////////////////////////////
// BEGIN PARAMS
///////////////////////////////////////////////////////////////////////////////
package btree package btree
import "sync" import (
"sync"
"sync/atomic"
)
// degree is the B-Tree degree, which is equal to maximum number of children const (
// pre node times two. degree = 128
// The default is 128, which means each node can have 255 items and 256 child maxItems = degree*2 - 1 // max items per node. max children is +1
// nodes. minItems = maxItems / 2
const degree = 128 )
// kind is the item type. type BTreeG[T any] struct {
// It's important to use the equal symbol, which tells Go to create an alias of
// the type, rather than creating an entirely new type.
type kind = interface{}
// contextKind is the kind of context that can be passed to NewOptions and the
// less function
type contextKind = interface{}
// less returns true if A is less than B.
// The value of context will be whatever was passed to NewOptions through the
// Options.Context field, otherwise nil if the field was not set.
func less(a, b kind, context contextKind) bool {
return context.(func(a, b contextKind) bool)(a, b)
}
// BTree aliases
// These are aliases to the local bTree types and functions, which are exported
// to allow for public use at a package level.
// Rename them if desired, or comment them out to make the library private.
type BTree = bTree
type Options = bOptions
type PathHint = bPathHint
type Iter = bIter
func New(less func(a, b kind) bool) *bTree { return bNew() }
func NewOptions(opts bOptions) *bTree { return bNewOptions(opts) }
// The functions below, which begin with "test*", are required by the
// btree_test.go file. If you choose not use include the btree_test.go file in
// your project then these functions may be omitted.
// testCustomSeed can be used to generate a custom random seed for testing.
// Returning false will use time.Now().UnixNano()
func testCustomSeed() (seed int64, ok bool) {
return 0, false
}
// testMakeItem must return a valid item for testing.
// It's required that the returned item maintains equal order as the
// provided int, such that:
// testMakeItem(0) < testMakeItem(1) < testMakeItem(2) < testMakeItem(10)
func testMakeItem(x int) (item kind) {
return x
}
// testNewBTree must return an operational btree for testing.
func testNewBTree() *bTree {
return bNewOptions(bOptions{
Context: func(a, b contextKind) bool {
if a == nil {
return b != nil
} else if b == nil {
return false
}
return a.(int) < b.(int)
},
})
}
///////////////////////////////////////////////////////////////////////////////
// END PARAMS
///////////////////////////////////////////////////////////////////////////////
// Do not edit code below this line.
const maxItems = degree*2 - 1 // max items per node. max children is +1
const minItems = maxItems / 2
type bTree struct {
mu *sync.RWMutex mu *sync.RWMutex
cow *cow cow uint64
root *node root *node[T]
count int count int
ctx contextKind
locks bool locks bool
empty kind less func(a, b T) bool
empty T
} }
type node struct { type node[T any] struct {
cow *cow cow uint64
count int count int
items []kind items []T
children *[]*node children *[]*node[T]
} }
type cow struct { var gcow uint64
_ int // cannot be an empty struct
}
func (tr *bTree) newNode(leaf bool) *node {
n := &node{cow: tr.cow}
if !leaf {
n.children = new([]*node)
}
return n
}
// leaf returns true if the node is a leaf.
func (n *node) leaf() bool {
return n.children == nil
}
// PathHint is a utility type used with the *Hint() functions. Hints provide // PathHint is a utility type used with the *Hint() functions. Hints provide
// faster operations for clustered keys. // faster operations for clustered keys.
type bPathHint struct { type PathHint struct {
used [8]bool used [8]bool
path [8]uint8 path [8]uint8
} }
type bOptions struct { // Options for passing to New when creating a new BTree.
type Options struct {
NoLocks bool NoLocks bool
Context contextKind
} }
// New returns a new BTree // New returns a new BTree
func bNew() *bTree { func NewBTreeG[T any](less func(a, b T) bool) *BTreeG[T] {
return bNewOptions(bOptions{}) return NewBTreeGOptions(less, Options{})
} }
func bNewOptions(opts bOptions) *bTree { func NewBTreeGOptions[T any](less func(a, b T) bool, opts Options) *BTreeG[T] {
tr := new(bTree) tr := new(BTreeG[T])
tr.cow = new(cow) tr.cow = atomic.AddUint64(&gcow, 1)
tr.mu = new(sync.RWMutex) tr.mu = new(sync.RWMutex)
tr.ctx = opts.Context tr.less = less
tr.locks = !opts.NoLocks tr.locks = !opts.NoLocks
return tr return tr
} }
// Less is a convenience function that performs a comparison of two items // Less is a convenience function that performs a comparison of two items
// using the same "less" function provided to New. // using the same "less" function provided to New.
func (tr *bTree) Less(a, b kind) bool { func (tr *BTreeG[T]) Less(a, b T) bool {
return less(a, b, tr.ctx) return tr.less(a, b)
} }
func (tr *bTree) find(n *node, key kind, func (tr *BTreeG[T]) newNode(leaf bool) *node[T] {
hint *bPathHint, depth int, n := &node[T]{cow: tr.cow}
if !leaf {
n.children = new([]*node[T])
}
return n
}
// leaf returns true if the node is a leaf.
func (n *node[T]) leaf() bool {
return n.children == nil
}
func (tr *BTreeG[T]) bsearch(n *node[T], key T) (index int, found bool) {
low, high := 0, len(n.items)
for low < high {
h := int(uint(low+high) >> 1)
if !tr.less(key, n.items[h]) {
low = h + 1
} else {
high = h
}
}
if low > 0 && !tr.less(n.items[low-1], key) {
return low - 1, true
}
return low, false
}
func (tr *BTreeG[T]) find(n *node[T], key T, hint *PathHint, depth int,
) (index int, found bool) { ) (index int, found bool) {
if hint == nil { if hint == nil {
// fast path for no hinting return tr.bsearch(n, key)
low := 0
high := len(n.items)
for low < high {
mid := (low + high) / 2
if !tr.Less(key, n.items[mid]) {
low = mid + 1
} else {
high = mid
}
}
if low > 0 && !tr.Less(n.items[low-1], key) {
return low - 1, true
}
return low, false
} }
return tr.hintsearch(n, key, hint, depth)
}
// Try using hint. func (tr *BTreeG[T]) hintsearch(n *node[T], key T, hint *PathHint, depth int,
) (index int, found bool) {
// Best case finds the exact match, updates the hint and returns. // Best case finds the exact match, updates the hint and returns.
// Worst case, updates the low and high bounds to binary search between. // Worst case, updates the low and high bounds to binary search between.
low := 0 low := 0
@ -247,17 +178,21 @@ path_match:
} }
// SetHint sets or replace a value for a key using a path hint // SetHint sets or replace a value for a key using a path hint
func (tr *bTree) SetHint(item kind, hint *bPathHint) (prev kind, replaced bool) { func (tr *BTreeG[T]) SetHint(item T, hint *PathHint) (prev T, replaced bool) {
if tr.lock() { if tr.locks {
defer tr.unlock() tr.mu.Lock()
prev, replaced = tr.setHint(item, hint)
tr.mu.Unlock()
} else {
prev, replaced = tr.setHint(item, hint)
} }
return tr.setHint(item, hint) return prev, replaced
} }
func (tr *bTree) setHint(item kind, hint *bPathHint) (prev kind, replaced bool) { func (tr *BTreeG[T]) setHint(item T, hint *PathHint) (prev T, replaced bool) {
if tr.root == nil { if tr.root == nil {
tr.root = tr.newNode(true) tr.root = tr.newNode(true)
tr.root.items = append([]kind{}, item) tr.root.items = append([]T{}, item)
tr.root.count = 1 tr.root.count = 1
tr.count = 1 tr.count = 1
return tr.empty, false return tr.empty, false
@ -267,9 +202,9 @@ func (tr *bTree) setHint(item kind, hint *bPathHint) (prev kind, replaced bool)
left := tr.cowLoad(&tr.root) left := tr.cowLoad(&tr.root)
right, median := tr.nodeSplit(left) right, median := tr.nodeSplit(left)
tr.root = tr.newNode(false) tr.root = tr.newNode(false)
*tr.root.children = make([]*node, 0, maxItems+1) *tr.root.children = make([]*node[T], 0, maxItems+1)
*tr.root.children = append([]*node{}, left, right) *tr.root.children = append([]*node[T]{}, left, right)
tr.root.items = append([]kind{}, median) tr.root.items = append([]T{}, median)
tr.root.updateCount() tr.root.updateCount()
return tr.setHint(item, hint) return tr.setHint(item, hint)
} }
@ -281,39 +216,61 @@ func (tr *bTree) setHint(item kind, hint *bPathHint) (prev kind, replaced bool)
} }
// Set or replace a value for a key // Set or replace a value for a key
func (tr *bTree) Set(item kind) (kind, bool) { func (tr *BTreeG[T]) Set(item T) (T, bool) {
return tr.SetHint(item, nil) return tr.SetHint(item, nil)
} }
func (tr *bTree) nodeSplit(n *node) (right *node, median kind) { func (tr *BTreeG[T]) nodeSplit(n *node[T]) (right *node[T], median T) {
i := maxItems / 2 i := maxItems / 2
median = n.items[i] median = n.items[i]
// left node const sliceItems = true
left := tr.newNode(n.leaf())
left.items = make([]kind, len(n.items[:i]), maxItems/2)
copy(left.items, n.items[:i])
if !n.leaf() {
*left.children = make([]*node, len((*n.children)[:i+1]), maxItems+1)
copy(*left.children, (*n.children)[:i+1])
}
left.updateCount()
// right node // right node
right = tr.newNode(n.leaf()) right = tr.newNode(n.leaf())
right.items = make([]kind, len(n.items[i+1:]), maxItems/2) if sliceItems {
copy(right.items, n.items[i+1:]) right.items = n.items[i+1:]
if !n.leaf() { if !n.leaf() {
*right.children = make([]*node, len((*n.children)[i+1:]), maxItems+1) *right.children = (*n.children)[i+1:]
copy(*right.children, (*n.children)[i+1:]) }
} else {
right.items = make([]T, len(n.items[i+1:]), maxItems/2)
copy(right.items, n.items[i+1:])
if !n.leaf() {
*right.children =
make([]*node[T], len((*n.children)[i+1:]), maxItems+1)
copy(*right.children, (*n.children)[i+1:])
}
} }
right.updateCount() right.updateCount()
*n = *left // left node
if sliceItems {
n.items[i] = tr.empty
n.items = n.items[:i:i]
if !n.leaf() {
*n.children = (*n.children)[: i+1 : i+1]
}
} else {
for j := i; j < len(n.items); j++ {
n.items[j] = tr.empty
}
if !n.leaf() {
for j := i + 1; j < len((*n.children)); j++ {
(*n.children)[j] = nil
}
}
n.items = n.items[:i]
if !n.leaf() {
*n.children = (*n.children)[:i+1]
}
}
n.updateCount()
return right, median return right, median
} }
func (n *node) updateCount() { func (n *node[T]) updateCount() {
n.count = len(n.items) n.count = len(n.items)
if !n.leaf() { if !n.leaf() {
for i := 0; i < len(*n.children); i++ { for i := 0; i < len(*n.children); i++ {
@ -326,33 +283,42 @@ func (n *node) updateCount() {
// called outside of heavy copy-on-write situations. Marking it "noinline" // called outside of heavy copy-on-write situations. Marking it "noinline"
// allows for the parent cowLoad to be inlined. // allows for the parent cowLoad to be inlined.
// go:noinline // go:noinline
func (tr *bTree) copy(n *node) *node { func (tr *BTreeG[T]) copy(n *node[T]) *node[T] {
n2 := new(node) n2 := new(node[T])
n2.cow = tr.cow n2.cow = tr.cow
n2.count = n.count n2.count = n.count
n2.items = make([]kind, len(n.items), cap(n.items)) n2.items = make([]T, len(n.items), cap(n.items))
copy(n2.items, n.items) copy(n2.items, n.items)
if !n.leaf() { if !n.leaf() {
n2.children = new([]*node) n2.children = new([]*node[T])
*n2.children = make([]*node, len(*n.children), maxItems+1) *n2.children = make([]*node[T], len(*n.children), maxItems+1)
copy(*n2.children, *n.children) copy(*n2.children, *n.children)
} }
return n2 return n2
} }
// cowLoad loads the provided node and, if needed, performs a copy-on-write. // cowLoad loads the provided node and, if needed, performs a copy-on-write.
func (tr *bTree) cowLoad(cn **node) *node { func (tr *BTreeG[T]) cowLoad(cn **node[T]) *node[T] {
if (*cn).cow != tr.cow { if (*cn).cow != tr.cow {
*cn = tr.copy(*cn) *cn = tr.copy(*cn)
} }
return *cn return *cn
} }
func (tr *bTree) nodeSet(cn **node, item kind, func (tr *BTreeG[T]) nodeSet(cn **node[T], item T,
hint *bPathHint, depth int, hint *PathHint, depth int,
) (prev kind, replaced bool, split bool) { ) (prev T, replaced bool, split bool) {
n := tr.cowLoad(cn) if (*cn).cow != tr.cow {
i, found := tr.find(n, item, hint, depth) *cn = tr.copy(*cn)
}
n := *cn
var i int
var found bool
if hint == nil {
i, found = tr.bsearch(n, item)
} else {
i, found = tr.hintsearch(n, item, hint, depth)
}
if found { if found {
prev = n.items[i] prev = n.items[i]
n.items[i] = item n.items[i] = item
@ -388,7 +354,7 @@ func (tr *bTree) nodeSet(cn **node, item kind,
return prev, replaced, false return prev, replaced, false
} }
func (tr *bTree) Scan(iter func(item kind) bool) { func (tr *BTreeG[T]) Scan(iter func(item T) bool) {
if tr.rlock() { if tr.rlock() {
defer tr.runlock() defer tr.runlock()
} }
@ -398,7 +364,7 @@ func (tr *bTree) Scan(iter func(item kind) bool) {
tr.root.scan(iter) tr.root.scan(iter)
} }
func (n *node) scan(iter func(item kind) bool) bool { func (n *node[T]) scan(iter func(item T) bool) bool {
if n.leaf() { if n.leaf() {
for i := 0; i < len(n.items); i++ { for i := 0; i < len(n.items); i++ {
if !iter(n.items[i]) { if !iter(n.items[i]) {
@ -419,15 +385,36 @@ func (n *node) scan(iter func(item kind) bool) bool {
} }
// Get a value for key // Get a value for key
func (tr *bTree) Get(key kind) (kind, bool) { func (tr *BTreeG[T]) Get(key T) (T, bool) {
return tr.GetHint(key, nil) if tr.locks {
return tr.GetHint(key, nil)
}
if tr.root == nil {
return tr.empty, false
}
n := tr.root
for {
i, found := tr.bsearch(n, key)
if found {
return n.items[i], true
}
if n.children == nil {
return tr.empty, false
}
n = (*n.children)[i]
}
} }
// GetHint gets a value for key using a path hint // GetHint gets a value for key using a path hint
func (tr *bTree) GetHint(key kind, hint *bPathHint) (kind, bool) { func (tr *BTreeG[T]) GetHint(key T, hint *PathHint) (value T, ok bool) {
if tr.rlock() { if tr.rlock() {
defer tr.runlock() defer tr.runlock()
} }
return tr.getHint(key, hint)
}
// GetHint gets a value for key using a path hint
func (tr *BTreeG[T]) getHint(key T, hint *PathHint) (T, bool) {
if tr.root == nil { if tr.root == nil {
return tr.empty, false return tr.empty, false
} }
@ -447,24 +434,27 @@ func (tr *bTree) GetHint(key kind, hint *bPathHint) (kind, bool) {
} }
// Len returns the number of items in the tree // Len returns the number of items in the tree
func (tr *bTree) Len() int { func (tr *BTreeG[T]) Len() int {
return tr.count return tr.count
} }
// Delete a value for a key // Delete a value for a key and returns the deleted value.
func (tr *bTree) Delete(key kind) (kind, bool) { // Returns false if there was no value by that key found.
func (tr *BTreeG[T]) Delete(key T) (T, bool) {
return tr.DeleteHint(key, nil) return tr.DeleteHint(key, nil)
} }
// DeleteHint deletes a value for a key using a path hint // DeleteHint deletes a value for a key using a path hint and returns the
func (tr *bTree) DeleteHint(key kind, hint *bPathHint) (kind, bool) { // deleted value.
// Returns false if there was no value by that key found.
func (tr *BTreeG[T]) DeleteHint(key T, hint *PathHint) (T, bool) {
if tr.lock() { if tr.lock() {
defer tr.unlock() defer tr.unlock()
} }
return tr.deleteHint(key, hint) return tr.deleteHint(key, hint)
} }
func (tr *bTree) deleteHint(key kind, hint *bPathHint) (kind, bool) { func (tr *BTreeG[T]) deleteHint(key T, hint *PathHint) (T, bool) {
if tr.root == nil { if tr.root == nil {
return tr.empty, false return tr.empty, false
} }
@ -482,9 +472,9 @@ func (tr *bTree) deleteHint(key kind, hint *bPathHint) (kind, bool) {
return prev, true return prev, true
} }
func (tr *bTree) delete(cn **node, max bool, key kind, func (tr *BTreeG[T]) delete(cn **node[T], max bool, key T,
hint *bPathHint, depth int, hint *PathHint, depth int,
) (kind, bool) { ) (T, bool) {
n := tr.cowLoad(cn) n := tr.cowLoad(cn)
var i int var i int
var found bool var found bool
@ -506,7 +496,7 @@ func (tr *bTree) delete(cn **node, max bool, key kind,
return tr.empty, false return tr.empty, false
} }
var prev kind var prev T
var deleted bool var deleted bool
if found { if found {
if max { if max {
@ -529,13 +519,12 @@ func (tr *bTree) delete(cn **node, max bool, key kind,
tr.nodeRebalance(n, i) tr.nodeRebalance(n, i)
} }
return prev, true return prev, true
} }
// nodeRebalance rebalances the child nodes following a delete operation. // nodeRebalance rebalances the child nodes following a delete operation.
// Provide the index of the child node with the number of items that fell // Provide the index of the child node with the number of items that fell
// below minItems. // below minItems.
func (tr *bTree) nodeRebalance(n *node, i int) { func (tr *BTreeG[T]) nodeRebalance(n *node[T], i int) {
if i == len(n.items) { if i == len(n.items) {
i-- i--
} }
@ -618,7 +607,7 @@ func (tr *bTree) nodeRebalance(n *node, i int) {
// Ascend the tree within the range [pivot, last] // Ascend the tree within the range [pivot, last]
// Pass nil for pivot to scan all item in ascending order // Pass nil for pivot to scan all item in ascending order
// Return false to stop iterating // Return false to stop iterating
func (tr *bTree) Ascend(pivot kind, iter func(item kind) bool) { func (tr *BTreeG[T]) Ascend(pivot T, iter func(item T) bool) {
if tr.rlock() { if tr.rlock() {
defer tr.runlock() defer tr.runlock()
} }
@ -630,8 +619,8 @@ func (tr *bTree) Ascend(pivot kind, iter func(item kind) bool) {
// The return value of this function determines whether we should keep iterating // The return value of this function determines whether we should keep iterating
// upon this functions return. // upon this functions return.
func (tr *bTree) ascend(n *node, pivot kind, func (tr *BTreeG[T]) ascend(n *node[T], pivot T,
hint *bPathHint, depth int, iter func(item kind) bool, hint *PathHint, depth int, iter func(item T) bool,
) bool { ) bool {
i, found := tr.find(n, pivot, hint, depth) i, found := tr.find(n, pivot, hint, depth)
if !found { if !found {
@ -658,7 +647,7 @@ func (tr *bTree) ascend(n *node, pivot kind,
return true return true
} }
func (tr *bTree) Reverse(iter func(item kind) bool) { func (tr *BTreeG[T]) Reverse(iter func(item T) bool) {
if tr.rlock() { if tr.rlock() {
defer tr.runlock() defer tr.runlock()
} }
@ -668,7 +657,7 @@ func (tr *bTree) Reverse(iter func(item kind) bool) {
tr.root.reverse(iter) tr.root.reverse(iter)
} }
func (n *node) reverse(iter func(item kind) bool) bool { func (n *node[T]) reverse(iter func(item T) bool) bool {
if n.leaf() { if n.leaf() {
for i := len(n.items) - 1; i >= 0; i-- { for i := len(n.items) - 1; i >= 0; i-- {
if !iter(n.items[i]) { if !iter(n.items[i]) {
@ -694,7 +683,7 @@ func (n *node) reverse(iter func(item kind) bool) bool {
// Descend the tree within the range [pivot, first] // Descend the tree within the range [pivot, first]
// Pass nil for pivot to scan all item in descending order // Pass nil for pivot to scan all item in descending order
// Return false to stop iterating // Return false to stop iterating
func (tr *bTree) Descend(pivot kind, iter func(item kind) bool) { func (tr *BTreeG[T]) Descend(pivot T, iter func(item T) bool) {
if tr.rlock() { if tr.rlock() {
defer tr.runlock() defer tr.runlock()
} }
@ -704,8 +693,8 @@ func (tr *bTree) Descend(pivot kind, iter func(item kind) bool) {
tr.descend(tr.root, pivot, nil, 0, iter) tr.descend(tr.root, pivot, nil, 0, iter)
} }
func (tr *bTree) descend(n *node, pivot kind, func (tr *BTreeG[T]) descend(n *node[T], pivot T,
hint *bPathHint, depth int, iter func(item kind) bool, hint *PathHint, depth int, iter func(item T) bool,
) bool { ) bool {
i, found := tr.find(n, pivot, hint, depth) i, found := tr.find(n, pivot, hint, depth)
if !found { if !found {
@ -730,7 +719,7 @@ func (tr *bTree) descend(n *node, pivot kind,
} }
// Load is for bulk loading pre-sorted items // Load is for bulk loading pre-sorted items
func (tr *bTree) Load(item kind) (kind, bool) { func (tr *BTreeG[T]) Load(item T) (T, bool) {
if tr.lock() { if tr.lock() {
defer tr.unlock() defer tr.unlock()
} }
@ -765,8 +754,8 @@ func (tr *bTree) Load(item kind) (kind, bool) {
} }
// Min returns the minimum item in tree. // Min returns the minimum item in tree.
// Returns nil if the tree has no items. // Returns nil if the treex has no items.
func (tr *bTree) Min() (kind, bool) { func (tr *BTreeG[T]) Min() (T, bool) {
if tr.rlock() { if tr.rlock() {
defer tr.runlock() defer tr.runlock()
} }
@ -784,7 +773,7 @@ func (tr *bTree) Min() (kind, bool) {
// Max returns the maximum item in tree. // Max returns the maximum item in tree.
// Returns nil if the tree has no items. // Returns nil if the tree has no items.
func (tr *bTree) Max() (kind, bool) { func (tr *BTreeG[T]) Max() (T, bool) {
if tr.rlock() { if tr.rlock() {
defer tr.runlock() defer tr.runlock()
} }
@ -802,7 +791,7 @@ func (tr *bTree) Max() (kind, bool) {
// PopMin removes the minimum item in tree and returns it. // PopMin removes the minimum item in tree and returns it.
// Returns nil if the tree has no items. // Returns nil if the tree has no items.
func (tr *bTree) PopMin() (kind, bool) { func (tr *BTreeG[T]) PopMin() (T, bool) {
if tr.lock() { if tr.lock() {
defer tr.unlock() defer tr.unlock()
} }
@ -810,7 +799,7 @@ func (tr *bTree) PopMin() (kind, bool) {
return tr.empty, false return tr.empty, false
} }
n := tr.cowLoad(&tr.root) n := tr.cowLoad(&tr.root)
var item kind var item T
for { for {
n.count-- // optimistically update counts n.count-- // optimistically update counts
if n.leaf() { if n.leaf() {
@ -841,9 +830,9 @@ func (tr *bTree) PopMin() (kind, bool) {
return tr.deleteHint(item, nil) return tr.deleteHint(item, nil)
} }
// PopMax removes the minimum item in tree and returns it. // PopMax removes the maximum item in tree and returns it.
// Returns nil if the tree has no items. // Returns nil if the tree has no items.
func (tr *bTree) PopMax() (kind, bool) { func (tr *BTreeG[T]) PopMax() (T, bool) {
if tr.lock() { if tr.lock() {
defer tr.unlock() defer tr.unlock()
} }
@ -851,7 +840,7 @@ func (tr *bTree) PopMax() (kind, bool) {
return tr.empty, false return tr.empty, false
} }
n := tr.cowLoad(&tr.root) n := tr.cowLoad(&tr.root)
var item kind var item T
for { for {
n.count-- // optimistically update counts n.count-- // optimistically update counts
if n.leaf() { if n.leaf() {
@ -883,7 +872,7 @@ func (tr *bTree) PopMax() (kind, bool) {
// GetAt returns the value at index. // GetAt returns the value at index.
// Return nil if the tree is empty or the index is out of bounds. // Return nil if the tree is empty or the index is out of bounds.
func (tr *bTree) GetAt(index int) (kind, bool) { func (tr *BTreeG[T]) GetAt(index int) (T, bool) {
if tr.rlock() { if tr.rlock() {
defer tr.runlock() defer tr.runlock()
} }
@ -910,7 +899,7 @@ func (tr *bTree) GetAt(index int) (kind, bool) {
// DeleteAt deletes the item at index. // DeleteAt deletes the item at index.
// Return nil if the tree is empty or the index is out of bounds. // Return nil if the tree is empty or the index is out of bounds.
func (tr *bTree) DeleteAt(index int) (kind, bool) { func (tr *BTreeG[T]) DeleteAt(index int) (T, bool) {
if tr.lock() { if tr.lock() {
defer tr.unlock() defer tr.unlock()
} }
@ -919,7 +908,7 @@ func (tr *bTree) DeleteAt(index int) (kind, bool) {
} }
var pathbuf [8]uint8 // track the path var pathbuf [8]uint8 // track the path
path := pathbuf[:0] path := pathbuf[:0]
var item kind var item T
n := tr.cowLoad(&tr.root) n := tr.cowLoad(&tr.root)
outer: outer:
for { for {
@ -955,7 +944,7 @@ outer:
n = tr.cowLoad(&(*n.children)[i]) n = tr.cowLoad(&(*n.children)[i])
} }
// revert the counts // revert the counts
var hint bPathHint var hint PathHint
n = tr.root n = tr.root
for i := 0; i < len(path); i++ { for i := 0; i < len(path); i++ {
if i < len(hint.path) { if i < len(hint.path) {
@ -972,7 +961,7 @@ outer:
// Height returns the height of the tree. // Height returns the height of the tree.
// Returns zero if tree has no items. // Returns zero if tree has no items.
func (tr *bTree) Height() int { func (tr *BTreeG[T]) Height() int {
if tr.rlock() { if tr.rlock() {
defer tr.runlock() defer tr.runlock()
} }
@ -992,7 +981,7 @@ func (tr *bTree) Height() int {
// Walk iterates over all items in tree, in order. // Walk iterates over all items in tree, in order.
// The items param will contain one or more items. // The items param will contain one or more items.
func (tr *bTree) Walk(iter func(item []kind) bool) { func (tr *BTreeG[T]) Walk(iter func(item []T) bool) {
if tr.rlock() { if tr.rlock() {
defer tr.runlock() defer tr.runlock()
} }
@ -1001,7 +990,7 @@ func (tr *bTree) Walk(iter func(item []kind) bool) {
} }
} }
func (n *node) walk(iter func(item []kind) bool) bool { func (n *node[T]) walk(iter func(item []T) bool) bool {
if n.leaf() { if n.leaf() {
if !iter(n.items) { if !iter(n.items) {
return false return false
@ -1020,60 +1009,60 @@ func (n *node) walk(iter func(item []kind) bool) bool {
// Copy the tree. This is a copy-on-write operation and is very fast because // Copy the tree. This is a copy-on-write operation and is very fast because
// it only performs a shadowed copy. // it only performs a shadowed copy.
func (tr *bTree) Copy() *bTree { func (tr *BTreeG[T]) Copy() *BTreeG[T] {
if tr.lock() { if tr.lock() {
defer tr.unlock() defer tr.unlock()
} }
tr.cow = new(cow) tr.cow = atomic.AddUint64(&gcow, 1)
tr2 := new(bTree) tr2 := new(BTreeG[T])
*tr2 = *tr *tr2 = *tr
tr2.mu = new(sync.RWMutex) tr2.mu = new(sync.RWMutex)
tr2.cow = new(cow) tr2.cow = atomic.AddUint64(&gcow, 1)
return tr2 return tr2
} }
func (tr *bTree) lock() bool { func (tr *BTreeG[T]) lock() bool {
if tr.locks { if tr.locks {
tr.mu.Lock() tr.mu.Lock()
} }
return tr.locks return tr.locks
} }
func (tr *bTree) unlock() { func (tr *BTreeG[T]) unlock() {
tr.mu.Unlock() tr.mu.Unlock()
} }
func (tr *bTree) rlock() bool { func (tr *BTreeG[T]) rlock() bool {
if tr.locks { if tr.locks {
tr.mu.RLock() tr.mu.RLock()
} }
return tr.locks return tr.locks
} }
func (tr *bTree) runlock() { func (tr *BTreeG[T]) runlock() {
tr.mu.RUnlock() tr.mu.RUnlock()
} }
// Iter represents an iterator // Iter represents an iterator
type bIter struct { type GenericIter[T any] struct {
tr *bTree tr *BTreeG[T]
locked bool locked bool
seeked bool seeked bool
atstart bool atstart bool
atend bool atend bool
stack []iterStackItem stack []genericIterStackItem[T]
item kind item T
} }
type iterStackItem struct { type genericIterStackItem[T any] struct {
n *node n *node[T]
i int i int
} }
// Iter returns a read-only iterator. // Iter returns a read-only iterator.
// The Release method must be called finished with iterator. // The Release method must be called finished with iterator.
func (tr *bTree) Iter() bIter { func (tr *BTreeG[T]) Iter() GenericIter[T] {
var iter bIter var iter GenericIter[T]
iter.tr = tr iter.tr = tr
iter.locked = tr.rlock() iter.locked = tr.rlock()
return iter return iter
@ -1081,7 +1070,7 @@ func (tr *bTree) Iter() bIter {
// Seek to item greater-or-equal-to key. // Seek to item greater-or-equal-to key.
// Returns false if there was no item found. // Returns false if there was no item found.
func (iter *bIter) Seek(key kind) bool { func (iter *GenericIter[T]) Seek(key T) bool {
if iter.tr == nil { if iter.tr == nil {
return false return false
} }
@ -1093,16 +1082,14 @@ func (iter *bIter) Seek(key kind) bool {
n := iter.tr.root n := iter.tr.root
for { for {
i, found := iter.tr.find(n, key, nil, 0) i, found := iter.tr.find(n, key, nil, 0)
iter.stack = append(iter.stack, iterStackItem{n, i}) iter.stack = append(iter.stack, genericIterStackItem[T]{n, i})
if found { if found {
iter.item = n.items[i]
return true return true
} }
if n.leaf() { if n.leaf() {
if i == len(n.items) { iter.stack[len(iter.stack)-1].i--
iter.stack = iter.stack[:0] return iter.Next()
return false
}
return true
} }
n = (*n.children)[i] n = (*n.children)[i]
} }
@ -1110,7 +1097,7 @@ func (iter *bIter) Seek(key kind) bool {
// First moves iterator to first item in tree. // First moves iterator to first item in tree.
// Returns false if the tree is empty. // Returns false if the tree is empty.
func (iter *bIter) First() bool { func (iter *GenericIter[T]) First() bool {
if iter.tr == nil { if iter.tr == nil {
return false return false
} }
@ -1123,7 +1110,7 @@ func (iter *bIter) First() bool {
} }
n := iter.tr.root n := iter.tr.root
for { for {
iter.stack = append(iter.stack, iterStackItem{n, 0}) iter.stack = append(iter.stack, genericIterStackItem[T]{n, 0})
if n.leaf() { if n.leaf() {
break break
} }
@ -1136,7 +1123,7 @@ func (iter *bIter) First() bool {
// Last moves iterator to last item in tree. // Last moves iterator to last item in tree.
// Returns false if the tree is empty. // Returns false if the tree is empty.
func (iter *bIter) Last() bool { func (iter *GenericIter[T]) Last() bool {
if iter.tr == nil { if iter.tr == nil {
return false return false
} }
@ -1147,7 +1134,7 @@ func (iter *bIter) Last() bool {
} }
n := iter.tr.root n := iter.tr.root
for { for {
iter.stack = append(iter.stack, iterStackItem{n, len(n.items)}) iter.stack = append(iter.stack, genericIterStackItem[T]{n, len(n.items)})
if n.leaf() { if n.leaf() {
iter.stack[len(iter.stack)-1].i-- iter.stack[len(iter.stack)-1].i--
break break
@ -1159,9 +1146,8 @@ func (iter *bIter) Last() bool {
return true return true
} }
// First moves iterator to first item in tree. // Release the iterator.
// Returns false if the tree is empty. func (iter *GenericIter[T]) Release() {
func (iter *bIter) Release() {
if iter.tr == nil { if iter.tr == nil {
return return
} }
@ -1176,7 +1162,7 @@ func (iter *bIter) Release() {
// Next moves iterator to the next item in iterator. // Next moves iterator to the next item in iterator.
// Returns false if the tree is empty or the iterator is at the end of // Returns false if the tree is empty or the iterator is at the end of
// the tree. // the tree.
func (iter *bIter) Next() bool { func (iter *GenericIter[T]) Next() bool {
if iter.tr == nil { if iter.tr == nil {
return false return false
} }
@ -1208,7 +1194,7 @@ func (iter *bIter) Next() bool {
} else { } else {
n := (*s.n.children)[s.i] n := (*s.n.children)[s.i]
for { for {
iter.stack = append(iter.stack, iterStackItem{n, 0}) iter.stack = append(iter.stack, genericIterStackItem[T]{n, 0})
if n.leaf() { if n.leaf() {
break break
} }
@ -1223,7 +1209,7 @@ func (iter *bIter) Next() bool {
// Prev moves iterator to the previous item in iterator. // Prev moves iterator to the previous item in iterator.
// Returns false if the tree is empty or the iterator is at the beginning of // Returns false if the tree is empty or the iterator is at the beginning of
// the tree. // the tree.
func (iter *bIter) Prev() bool { func (iter *GenericIter[T]) Prev() bool {
if iter.tr == nil { if iter.tr == nil {
return false return false
} }
@ -1256,7 +1242,7 @@ func (iter *bIter) Prev() bool {
} else { } else {
n := (*s.n.children)[s.i] n := (*s.n.children)[s.i]
for { for {
iter.stack = append(iter.stack, iterStackItem{n, len(n.items)}) iter.stack = append(iter.stack, genericIterStackItem[T]{n, len(n.items)})
if n.leaf() { if n.leaf() {
iter.stack[len(iter.stack)-1].i-- iter.stack[len(iter.stack)-1].i--
break break
@ -1270,6 +1256,48 @@ func (iter *bIter) Prev() bool {
} }
// Item returns the current iterator item. // Item returns the current iterator item.
func (iter *bIter) Item() kind { func (iter *GenericIter[T]) Item() T {
return iter.item return iter.item
} }
// Items returns all the items in order.
func (tr *BTreeG[T]) Items() []T {
items := make([]T, 0, tr.Len())
if tr.root != nil {
items = tr.root.aitems(items)
}
return items
}
func (n *node[T]) aitems(items []T) []T {
if n.leaf() {
return append(items, n.items...)
}
for i := 0; i < len(n.items); i++ {
items = (*n.children)[i].aitems(items)
items = append(items, n.items[i])
}
return (*n.children)[len(*n.children)-1].aitems(items)
}
// Generic BTree
// Deprecated: use BTreeG
type Generic[T any] struct {
*BTreeG[T]
}
// NewGeneric returns a generic BTree
// Deprecated: use NewBTreeG
func NewGeneric[T any](less func(a, b T) bool) *Generic[T] {
return &Generic[T]{NewBTreeGOptions(less, Options{})}
}
// NewGenericOptions returns a generic BTree
// Deprecated: use NewBTreeGOptions
func NewGenericOptions[T any](less func(a, b T) bool, opts Options) *Generic[T] {
return &Generic[T]{NewBTreeGOptions(less, opts)}
}
func (tr *Generic[T]) Copy() *Generic[T] {
return &Generic[T]{tr.BTreeG.Copy()}
}

1056
vendor/github.com/tidwall/btree/map.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

168
vendor/github.com/tidwall/btree/set.go generated vendored Normal file
View File

@ -0,0 +1,168 @@
package btree
type Set[K ordered] struct {
base Map[K, struct{}]
}
// Copy
func (tr *Set[K]) Copy() *Set[K] {
tr2 := new(Set[K])
tr2.base = *tr.base.Copy()
return tr2
}
// Insert an item
func (tr *Set[K]) Insert(key K) {
tr.base.Set(key, struct{}{})
}
func (tr *Set[K]) Scan(iter func(key K) bool) {
tr.base.Scan(func(key K, value struct{}) bool {
return iter(key)
})
}
// Get a value for key
func (tr *Set[K]) Contains(key K) bool {
_, ok := tr.base.Get(key)
return ok
}
// Len returns the number of items in the tree
func (tr *Set[K]) Len() int {
return tr.base.Len()
}
// Delete an item
func (tr *Set[K]) Delete(key K) {
tr.base.Delete(key)
}
// Ascend the tree within the range [pivot, last]
// Pass nil for pivot to scan all item in ascending order
// Return false to stop iterating
func (tr *Set[K]) Ascend(pivot K, iter func(key K) bool) {
tr.base.Ascend(pivot, func(key K, value struct{}) bool {
return iter(key)
})
}
func (tr *Set[K]) Reverse(iter func(key K) bool) {
tr.base.Reverse(func(key K, value struct{}) bool {
return iter(key)
})
}
// Descend the tree within the range [pivot, first]
// Pass nil for pivot to scan all item in descending order
// Return false to stop iterating
func (tr *Set[K]) Descend(pivot K, iter func(key K) bool) {
tr.base.Descend(pivot, func(key K, value struct{}) bool {
return iter(key)
})
}
// Load is for bulk loading pre-sorted items
func (tr *Set[K]) Load(key K) {
tr.base.Load(key, struct{}{})
}
// Min returns the minimum item in tree.
// Returns nil if the treex has no items.
func (tr *Set[K]) Min() (K, bool) {
key, _, ok := tr.base.Min()
return key, ok
}
// Max returns the maximum item in tree.
// Returns nil if the tree has no items.
func (tr *Set[K]) Max() (K, bool) {
key, _, ok := tr.base.Max()
return key, ok
}
// PopMin removes the minimum item in tree and returns it.
// Returns nil if the tree has no items.
func (tr *Set[K]) PopMin() (K, bool) {
key, _, ok := tr.base.PopMin()
return key, ok
}
// PopMax removes the maximum item in tree and returns it.
// Returns nil if the tree has no items.
func (tr *Set[K]) PopMax() (K, bool) {
key, _, ok := tr.base.PopMax()
return key, ok
}
// GetAt returns the value at index.
// Return nil if the tree is empty or the index is out of bounds.
func (tr *Set[K]) GetAt(index int) (K, bool) {
key, _, ok := tr.base.GetAt(index)
return key, ok
}
// DeleteAt deletes the item at index.
// Return nil if the tree is empty or the index is out of bounds.
func (tr *Set[K]) DeleteAt(index int) (K, bool) {
key, _, ok := tr.base.DeleteAt(index)
return key, ok
}
// Height returns the height of the tree.
// Returns zero if tree has no items.
func (tr *Set[K]) Height() int {
return tr.base.Height()
}
// SetIter represents an iterator for btree.Set
type SetIter[K ordered] struct {
base MapIter[K, struct{}]
}
// Iter returns a read-only iterator.
func (tr *Set[K]) Iter() SetIter[K] {
return SetIter[K]{tr.base.Iter()}
}
// Seek to item greater-or-equal-to key.
// Returns false if there was no item found.
func (iter *SetIter[K]) Seek(key K) bool {
return iter.base.Seek(key)
}
// First moves iterator to first item in tree.
// Returns false if the tree is empty.
func (iter *SetIter[K]) First() bool {
return iter.base.First()
}
// Last moves iterator to last item in tree.
// Returns false if the tree is empty.
func (iter *SetIter[K]) Last() bool {
return iter.base.Last()
}
// Next moves iterator to the next item in iterator.
// Returns false if the tree is empty or the iterator is at the end of
// the tree.
func (iter *SetIter[K]) Next() bool {
return iter.base.Next()
}
// Prev moves iterator to the previous item in iterator.
// Returns false if the tree is empty or the iterator is at the beginning of
// the tree.
func (iter *SetIter[K]) Prev() bool {
return iter.base.Prev()
}
// Key returns the current iterator item key.
func (iter *SetIter[K]) Key() K {
return iter.base.Key()
}
// Keys returns all the keys in order.
func (tr *Set[K]) Keys() []K {
return tr.base.Keys()
}

View File

@ -7,6 +7,7 @@ package buntdb
import ( import (
"bufio" "bufio"
"errors" "errors"
"fmt"
"io" "io"
"os" "os"
"sort" "sort"
@ -749,13 +750,13 @@ func (db *DB) Shrink() error {
if err := db.file.Close(); err != nil { if err := db.file.Close(); err != nil {
return err return err
} }
// Any failures below here is really bad. So just panic. // Any failures below here are really bad. So just panic.
if err := os.Rename(tmpname, fname); err != nil { if err := os.Rename(tmpname, fname); err != nil {
panic(err) panicErr(err)
} }
db.file, err = os.OpenFile(fname, os.O_CREATE|os.O_RDWR, 0666) db.file, err = os.OpenFile(fname, os.O_CREATE|os.O_RDWR, 0666)
if err != nil { if err != nil {
panic(err) panicErr(err)
} }
pos, err := db.file.Seek(0, 2) pos, err := db.file.Seek(0, 2)
if err != nil { if err != nil {
@ -766,6 +767,10 @@ func (db *DB) Shrink() error {
}() }()
} }
func panicErr(err error) error {
panic(fmt.Errorf("buntdb: %w", err))
}
// readLoad reads from the reader and loads commands into the database. // readLoad reads from the reader and loads commands into the database.
// modTime is the modified time of the reader, should be no greater than // modTime is the modified time of the reader, should be no greater than
// the current time.Now(). // the current time.Now().
@ -1209,10 +1214,10 @@ func (tx *Tx) Commit() error {
// should be killed to avoid corrupting the file. // should be killed to avoid corrupting the file.
pos, err := tx.db.file.Seek(-int64(n), 1) pos, err := tx.db.file.Seek(-int64(n), 1)
if err != nil { if err != nil {
panic(err) panicErr(err)
} }
if err := tx.db.file.Truncate(pos); err != nil { if err := tx.db.file.Truncate(pos); err != nil {
panic(err) panicErr(err)
} }
} }
tx.rollbackInner() tx.rollbackInner()

View File

@ -16,6 +16,10 @@ It has features such as [one line retrieval](#get-a-value), [dot notation paths]
Also check out [SJSON](https://github.com/tidwall/sjson) for modifying json, and the [JJ](https://github.com/tidwall/jj) command line tool. Also check out [SJSON](https://github.com/tidwall/sjson) for modifying json, and the [JJ](https://github.com/tidwall/jj) command line tool.
This README is a quick overview of how to use GJSON, for more information check out [GJSON Syntax](SYNTAX.md).
GJSON is also available for [Python](https://github.com/volans-/gjson-py) and [Rust](https://github.com/tidwall/gjson.rs)
Getting Started Getting Started
=============== ===============
@ -204,6 +208,9 @@ There are currently the following built-in modifiers:
- `@join`: Joins multiple objects into a single object. - `@join`: Joins multiple objects into a single object.
- `@keys`: Returns an array of keys for an object. - `@keys`: Returns an array of keys for an object.
- `@values`: Returns an array of values for an object. - `@values`: Returns an array of values for an object.
- `@tostr`: Converts json to a string. Wraps a json string.
- `@fromstr`: Converts a string from json. Unwraps a json string.
- `@group`: Groups arrays of objects. See [e4fc67c](https://github.com/tidwall/gjson/commit/e4fc67c92aeebf2089fabc7872f010e340d105db).
### Modifier arguments ### Modifier arguments

View File

@ -22,7 +22,7 @@ Use the [GJSON Playground](https://gjson.dev) to experiment with the syntax onli
A GJSON Path is intended to be easily expressed as a series of components seperated by a `.` character. A GJSON Path is intended to be easily expressed as a series of components seperated by a `.` character.
Along with `.` character, there are a few more that have special meaning, including `|`, `#`, `@`, `\`, `*`, and `?`. Along with `.` character, there are a few more that have special meaning, including `|`, `#`, `@`, `\`, `*`, `!`, and `?`.
## Example ## Example
@ -77,7 +77,7 @@ Special purpose characters, such as `.`, `*`, and `?` can be escaped with `\`.
fav\.movie "Deer Hunter" fav\.movie "Deer Hunter"
``` ```
You'll also need to make sure that the `\` character is correctly escaped when hardcoding a path in you source code. You'll also need to make sure that the `\` character is correctly escaped when hardcoding a path in your source code.
```go ```go
// Go // Go
@ -238,6 +238,9 @@ There are currently the following built-in modifiers:
- `@join`: Joins multiple objects into a single object. - `@join`: Joins multiple objects into a single object.
- `@keys`: Returns an array of keys for an object. - `@keys`: Returns an array of keys for an object.
- `@values`: Returns an array of values for an object. - `@values`: Returns an array of values for an object.
- `@tostr`: Converts json to a string. Wraps a json string.
- `@fromstr`: Converts a string from json. Unwraps a json string.
- `@group`: Groups arrays of objects. See [e4fc67c](https://github.com/tidwall/gjson/commit/e4fc67c92aeebf2089fabc7872f010e340d105db).
#### Modifier arguments #### Modifier arguments

View File

@ -2,7 +2,6 @@
package gjson package gjson
import ( import (
"encoding/json"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -214,6 +213,11 @@ func (t Result) IsArray() bool {
return t.Type == JSON && len(t.Raw) > 0 && t.Raw[0] == '[' return t.Type == JSON && len(t.Raw) > 0 && t.Raw[0] == '['
} }
// IsBool returns true if the result value is a JSON boolean.
func (t Result) IsBool() bool {
return t.Type == True || t.Type == False
}
// ForEach iterates through values. // ForEach iterates through values.
// If the result represents a non-existent value, then no values will be // If the result represents a non-existent value, then no values will be
// iterated. If the result is an Object, the iterator will pass the key and // iterated. If the result is an Object, the iterator will pass the key and
@ -771,7 +775,7 @@ func parseArrayPath(path string) (r arrayPathResult) {
} }
if path[i] == '.' { if path[i] == '.' {
r.part = path[:i] r.part = path[:i]
if !r.arrch && i < len(path)-1 && isDotPiperChar(path[i+1]) { if !r.arrch && i < len(path)-1 && isDotPiperChar(path[i+1:]) {
r.pipe = path[i+1:] r.pipe = path[i+1:]
r.piped = true r.piped = true
} else { } else {
@ -932,8 +936,23 @@ right:
} }
// peek at the next byte and see if it's a '@', '[', or '{'. // peek at the next byte and see if it's a '@', '[', or '{'.
func isDotPiperChar(c byte) bool { func isDotPiperChar(s string) bool {
return !DisableModifiers && (c == '@' || c == '[' || c == '{') if DisableModifiers {
return false
}
c := s[0]
if c == '@' {
// check that the next component is *not* a modifier.
i := 1
for ; i < len(s); i++ {
if s[i] == '.' || s[i] == '|' || s[i] == ':' {
break
}
}
_, ok := modifiers[s[1:i]]
return ok
}
return c == '[' || c == '{'
} }
type objectPathResult struct { type objectPathResult struct {
@ -955,7 +974,7 @@ func parseObjectPath(path string) (r objectPathResult) {
} }
if path[i] == '.' { if path[i] == '.' {
r.part = path[:i] r.part = path[:i]
if i < len(path)-1 && isDotPiperChar(path[i+1]) { if i < len(path)-1 && isDotPiperChar(path[i+1:]) {
r.pipe = path[i+1:] r.pipe = path[i+1:]
r.piped = true r.piped = true
} else { } else {
@ -985,7 +1004,7 @@ func parseObjectPath(path string) (r objectPathResult) {
continue continue
} else if path[i] == '.' { } else if path[i] == '.' {
r.part = string(epart) r.part = string(epart)
if i < len(path)-1 && isDotPiperChar(path[i+1]) { if i < len(path)-1 && isDotPiperChar(path[i+1:]) {
r.pipe = path[i+1:] r.pipe = path[i+1:]
r.piped = true r.piped = true
} else { } else {
@ -1819,17 +1838,64 @@ func isSimpleName(component string) bool {
return true return true
} }
func appendJSONString(dst []byte, s string) []byte { var hexchars = [...]byte{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f',
}
func appendHex16(dst []byte, x uint16) []byte {
return append(dst,
hexchars[x>>12&0xF], hexchars[x>>8&0xF],
hexchars[x>>4&0xF], hexchars[x>>0&0xF],
)
}
// AppendJSONString is a convenience function that converts the provided string
// to a valid JSON string and appends it to dst.
func AppendJSONString(dst []byte, s string) []byte {
dst = append(dst, make([]byte, len(s)+2)...)
dst = append(dst[:len(dst)-len(s)-2], '"')
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
if s[i] < ' ' || s[i] == '\\' || s[i] == '"' || s[i] > 126 { if s[i] < ' ' {
d, _ := json.Marshal(s) dst = append(dst, '\\')
return append(dst, string(d)...) switch s[i] {
case '\n':
dst = append(dst, 'n')
case '\r':
dst = append(dst, 'r')
case '\t':
dst = append(dst, 't')
default:
dst = append(dst, 'u')
dst = appendHex16(dst, uint16(s[i]))
}
} else if s[i] == '>' || s[i] == '<' || s[i] == '&' {
dst = append(dst, '\\', 'u')
dst = appendHex16(dst, uint16(s[i]))
} else if s[i] == '\\' {
dst = append(dst, '\\', '\\')
} else if s[i] == '"' {
dst = append(dst, '\\', '"')
} else if s[i] > 127 {
// read utf8 character
r, n := utf8.DecodeRuneInString(s[i:])
if n == 0 {
break
}
if r == utf8.RuneError && n == 1 {
dst = append(dst, `\ufffd`...)
} else if r == '\u2028' || r == '\u2029' {
dst = append(dst, `\u202`...)
dst = append(dst, hexchars[r&0xF])
} else {
dst = append(dst, s[i:i+n]...)
}
i = i + n - 1
} else {
dst = append(dst, s[i])
} }
} }
dst = append(dst, '"') return append(dst, '"')
dst = append(dst, s...)
dst = append(dst, '"')
return dst
} }
type parseContext struct { type parseContext struct {
@ -1919,14 +1985,14 @@ func Get(json, path string) Result {
if sub.name[0] == '"' && Valid(sub.name) { if sub.name[0] == '"' && Valid(sub.name) {
b = append(b, sub.name...) b = append(b, sub.name...)
} else { } else {
b = appendJSONString(b, sub.name) b = AppendJSONString(b, sub.name)
} }
} else { } else {
last := nameOfLast(sub.path) last := nameOfLast(sub.path)
if isSimpleName(last) { if isSimpleName(last) {
b = appendJSONString(b, last) b = AppendJSONString(b, last)
} else { } else {
b = appendJSONString(b, "_") b = AppendJSONString(b, "_")
} }
} }
b = append(b, ':') b = append(b, ':')
@ -2669,6 +2735,9 @@ var modifiers = map[string]func(json, arg string) string{
"valid": modValid, "valid": modValid,
"keys": modKeys, "keys": modKeys,
"values": modValues, "values": modValues,
"tostr": modToStr,
"fromstr": modFromStr,
"group": modGroup,
} }
// AddModifier binds a custom modifier command to the GJSON syntax. // AddModifier binds a custom modifier command to the GJSON syntax.
@ -2954,6 +3023,56 @@ func modValid(json, arg string) string {
return json return json
} }
// @fromstr converts a string to json
// "{\"id\":1023,\"name\":\"alert\"}" -> {"id":1023,"name":"alert"}
func modFromStr(json, arg string) string {
if !Valid(json) {
return ""
}
return Parse(json).String()
}
// @tostr converts a string to json
// {"id":1023,"name":"alert"} -> "{\"id\":1023,\"name\":\"alert\"}"
func modToStr(str, arg string) string {
return string(AppendJSONString(nil, str))
}
func modGroup(json, arg string) string {
res := Parse(json)
if !res.IsObject() {
return ""
}
var all [][]byte
res.ForEach(func(key, value Result) bool {
if !value.IsArray() {
return true
}
var idx int
value.ForEach(func(_, value Result) bool {
if idx == len(all) {
all = append(all, []byte{})
}
all[idx] = append(all[idx], ("," + key.Raw + ":" + value.Raw)...)
idx++
return true
})
return true
})
var data []byte
data = append(data, '[')
for i, item := range all {
if i > 0 {
data = append(data, ',')
}
data = append(data, '{')
data = append(data, item[1:]...)
data = append(data, '}')
}
data = append(data, ']')
return string(data)
}
// stringHeader instead of reflect.StringHeader // stringHeader instead of reflect.StringHeader
type stringHeader struct { type stringHeader struct {
data unsafe.Pointer data unsafe.Pointer
@ -3088,6 +3207,20 @@ func revSquash(json string) string {
return json return json
} }
// Paths returns the original GJSON paths for a Result where the Result came
// from a simple query path that returns an array, like:
//
// gjson.Get(json, "friends.#.first")
//
// The returned value will be in the form of a JSON array:
//
// ["friends.0.first","friends.1.first","friends.2.first"]
//
// The param 'json' must be the original JSON used when calling Get.
//
// Returns an empty string if the paths cannot be determined, which can happen
// when the Result came from a path that contained a multipath, modifier,
// or a nested query.
func (t Result) Paths(json string) []string { func (t Result) Paths(json string) []string {
if t.Indexes == nil { if t.Indexes == nil {
return nil return nil
@ -3103,8 +3236,20 @@ func (t Result) Paths(json string) []string {
return paths return paths
} }
// Path returns the original GJSON path for Result. // Path returns the original GJSON path for a Result where the Result came
// The json param must be the original JSON used when calling Get. // from a simple path that returns a single value, like:
//
// gjson.Get(json, "friends.#(last=Murphy)")
//
// The returned value will be in the form of a JSON string:
//
// "friends.0"
//
// The param 'json' must be the original JSON used when calling Get.
//
// Returns an empty string if the paths cannot be determined, which can happen
// when the Result came from a path that contained a multipath, modifier,
// or a nested query.
func (t Result) Path(json string) string { func (t Result) Path(json string) string {
var path []byte var path []byte
var comps []string // raw components var comps []string // raw components

3
vendor/golang.org/x/crypto/AUTHORS generated vendored
View File

@ -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.

View File

@ -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.

View File

@ -50,7 +50,7 @@ func (ih InvalidHashPrefixError) Error() string {
type InvalidCostError int type InvalidCostError int
func (ic InvalidCostError) Error() string { 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 range (%d,%d)", int(ic), MinCost, MaxCost)
} }
const ( const (
@ -82,11 +82,20 @@ type hashed struct {
minor byte 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 // 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 // cost. If the cost given is less than MinCost, the cost will be set to
// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package, // DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
// to compare the returned hashed password with its cleartext version. // 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) { func GenerateFromPassword(password []byte, cost int) ([]byte, error) {
if len(password) > 72 {
return nil, ErrPasswordTooLong
}
p, err := newFromPassword(password, cost) p, err := newFromPassword(password, cost)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -7,6 +7,8 @@
package sha3 package sha3
import "math/bits"
// rc stores the round constants for use in the ι step. // rc stores the round constants for use in the ι step.
var rc = [24]uint64{ var rc = [24]uint64{
0x0000000000000001, 0x0000000000000001,
@ -60,13 +62,13 @@ func keccakF1600(a *[25]uint64) {
bc0 = a[0] ^ d0 bc0 = a[0] ^ d0
t = a[6] ^ d1 t = a[6] ^ d1
bc1 = t<<44 | t>>(64-44) bc1 = bits.RotateLeft64(t, 44)
t = a[12] ^ d2 t = a[12] ^ d2
bc2 = t<<43 | t>>(64-43) bc2 = bits.RotateLeft64(t, 43)
t = a[18] ^ d3 t = a[18] ^ d3
bc3 = t<<21 | t>>(64-21) bc3 = bits.RotateLeft64(t, 21)
t = a[24] ^ d4 t = a[24] ^ d4
bc4 = t<<14 | t>>(64-14) bc4 = bits.RotateLeft64(t, 14)
a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i] a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i]
a[6] = bc1 ^ (bc3 &^ bc2) a[6] = bc1 ^ (bc3 &^ bc2)
a[12] = bc2 ^ (bc4 &^ bc3) a[12] = bc2 ^ (bc4 &^ bc3)
@ -74,15 +76,15 @@ func keccakF1600(a *[25]uint64) {
a[24] = bc4 ^ (bc1 &^ bc0) a[24] = bc4 ^ (bc1 &^ bc0)
t = a[10] ^ d0 t = a[10] ^ d0
bc2 = t<<3 | t>>(64-3) bc2 = bits.RotateLeft64(t, 3)
t = a[16] ^ d1 t = a[16] ^ d1
bc3 = t<<45 | t>>(64-45) bc3 = bits.RotateLeft64(t, 45)
t = a[22] ^ d2 t = a[22] ^ d2
bc4 = t<<61 | t>>(64-61) bc4 = bits.RotateLeft64(t, 61)
t = a[3] ^ d3 t = a[3] ^ d3
bc0 = t<<28 | t>>(64-28) bc0 = bits.RotateLeft64(t, 28)
t = a[9] ^ d4 t = a[9] ^ d4
bc1 = t<<20 | t>>(64-20) bc1 = bits.RotateLeft64(t, 20)
a[10] = bc0 ^ (bc2 &^ bc1) a[10] = bc0 ^ (bc2 &^ bc1)
a[16] = bc1 ^ (bc3 &^ bc2) a[16] = bc1 ^ (bc3 &^ bc2)
a[22] = bc2 ^ (bc4 &^ bc3) a[22] = bc2 ^ (bc4 &^ bc3)
@ -90,15 +92,15 @@ func keccakF1600(a *[25]uint64) {
a[9] = bc4 ^ (bc1 &^ bc0) a[9] = bc4 ^ (bc1 &^ bc0)
t = a[20] ^ d0 t = a[20] ^ d0
bc4 = t<<18 | t>>(64-18) bc4 = bits.RotateLeft64(t, 18)
t = a[1] ^ d1 t = a[1] ^ d1
bc0 = t<<1 | t>>(64-1) bc0 = bits.RotateLeft64(t, 1)
t = a[7] ^ d2 t = a[7] ^ d2
bc1 = t<<6 | t>>(64-6) bc1 = bits.RotateLeft64(t, 6)
t = a[13] ^ d3 t = a[13] ^ d3
bc2 = t<<25 | t>>(64-25) bc2 = bits.RotateLeft64(t, 25)
t = a[19] ^ d4 t = a[19] ^ d4
bc3 = t<<8 | t>>(64-8) bc3 = bits.RotateLeft64(t, 8)
a[20] = bc0 ^ (bc2 &^ bc1) a[20] = bc0 ^ (bc2 &^ bc1)
a[1] = bc1 ^ (bc3 &^ bc2) a[1] = bc1 ^ (bc3 &^ bc2)
a[7] = bc2 ^ (bc4 &^ bc3) a[7] = bc2 ^ (bc4 &^ bc3)
@ -106,15 +108,15 @@ func keccakF1600(a *[25]uint64) {
a[19] = bc4 ^ (bc1 &^ bc0) a[19] = bc4 ^ (bc1 &^ bc0)
t = a[5] ^ d0 t = a[5] ^ d0
bc1 = t<<36 | t>>(64-36) bc1 = bits.RotateLeft64(t, 36)
t = a[11] ^ d1 t = a[11] ^ d1
bc2 = t<<10 | t>>(64-10) bc2 = bits.RotateLeft64(t, 10)
t = a[17] ^ d2 t = a[17] ^ d2
bc3 = t<<15 | t>>(64-15) bc3 = bits.RotateLeft64(t, 15)
t = a[23] ^ d3 t = a[23] ^ d3
bc4 = t<<56 | t>>(64-56) bc4 = bits.RotateLeft64(t, 56)
t = a[4] ^ d4 t = a[4] ^ d4
bc0 = t<<27 | t>>(64-27) bc0 = bits.RotateLeft64(t, 27)
a[5] = bc0 ^ (bc2 &^ bc1) a[5] = bc0 ^ (bc2 &^ bc1)
a[11] = bc1 ^ (bc3 &^ bc2) a[11] = bc1 ^ (bc3 &^ bc2)
a[17] = bc2 ^ (bc4 &^ bc3) a[17] = bc2 ^ (bc4 &^ bc3)
@ -122,15 +124,15 @@ func keccakF1600(a *[25]uint64) {
a[4] = bc4 ^ (bc1 &^ bc0) a[4] = bc4 ^ (bc1 &^ bc0)
t = a[15] ^ d0 t = a[15] ^ d0
bc3 = t<<41 | t>>(64-41) bc3 = bits.RotateLeft64(t, 41)
t = a[21] ^ d1 t = a[21] ^ d1
bc4 = t<<2 | t>>(64-2) bc4 = bits.RotateLeft64(t, 2)
t = a[2] ^ d2 t = a[2] ^ d2
bc0 = t<<62 | t>>(64-62) bc0 = bits.RotateLeft64(t, 62)
t = a[8] ^ d3 t = a[8] ^ d3
bc1 = t<<55 | t>>(64-55) bc1 = bits.RotateLeft64(t, 55)
t = a[14] ^ d4 t = a[14] ^ d4
bc2 = t<<39 | t>>(64-39) bc2 = bits.RotateLeft64(t, 39)
a[15] = bc0 ^ (bc2 &^ bc1) a[15] = bc0 ^ (bc2 &^ bc1)
a[21] = bc1 ^ (bc3 &^ bc2) a[21] = bc1 ^ (bc3 &^ bc2)
a[2] = bc2 ^ (bc4 &^ bc3) a[2] = bc2 ^ (bc4 &^ bc3)
@ -151,13 +153,13 @@ func keccakF1600(a *[25]uint64) {
bc0 = a[0] ^ d0 bc0 = a[0] ^ d0
t = a[16] ^ d1 t = a[16] ^ d1
bc1 = t<<44 | t>>(64-44) bc1 = bits.RotateLeft64(t, 44)
t = a[7] ^ d2 t = a[7] ^ d2
bc2 = t<<43 | t>>(64-43) bc2 = bits.RotateLeft64(t, 43)
t = a[23] ^ d3 t = a[23] ^ d3
bc3 = t<<21 | t>>(64-21) bc3 = bits.RotateLeft64(t, 21)
t = a[14] ^ d4 t = a[14] ^ d4
bc4 = t<<14 | t>>(64-14) bc4 = bits.RotateLeft64(t, 14)
a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1] a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1]
a[16] = bc1 ^ (bc3 &^ bc2) a[16] = bc1 ^ (bc3 &^ bc2)
a[7] = bc2 ^ (bc4 &^ bc3) a[7] = bc2 ^ (bc4 &^ bc3)
@ -165,15 +167,15 @@ func keccakF1600(a *[25]uint64) {
a[14] = bc4 ^ (bc1 &^ bc0) a[14] = bc4 ^ (bc1 &^ bc0)
t = a[20] ^ d0 t = a[20] ^ d0
bc2 = t<<3 | t>>(64-3) bc2 = bits.RotateLeft64(t, 3)
t = a[11] ^ d1 t = a[11] ^ d1
bc3 = t<<45 | t>>(64-45) bc3 = bits.RotateLeft64(t, 45)
t = a[2] ^ d2 t = a[2] ^ d2
bc4 = t<<61 | t>>(64-61) bc4 = bits.RotateLeft64(t, 61)
t = a[18] ^ d3 t = a[18] ^ d3
bc0 = t<<28 | t>>(64-28) bc0 = bits.RotateLeft64(t, 28)
t = a[9] ^ d4 t = a[9] ^ d4
bc1 = t<<20 | t>>(64-20) bc1 = bits.RotateLeft64(t, 20)
a[20] = bc0 ^ (bc2 &^ bc1) a[20] = bc0 ^ (bc2 &^ bc1)
a[11] = bc1 ^ (bc3 &^ bc2) a[11] = bc1 ^ (bc3 &^ bc2)
a[2] = bc2 ^ (bc4 &^ bc3) a[2] = bc2 ^ (bc4 &^ bc3)
@ -181,15 +183,15 @@ func keccakF1600(a *[25]uint64) {
a[9] = bc4 ^ (bc1 &^ bc0) a[9] = bc4 ^ (bc1 &^ bc0)
t = a[15] ^ d0 t = a[15] ^ d0
bc4 = t<<18 | t>>(64-18) bc4 = bits.RotateLeft64(t, 18)
t = a[6] ^ d1 t = a[6] ^ d1
bc0 = t<<1 | t>>(64-1) bc0 = bits.RotateLeft64(t, 1)
t = a[22] ^ d2 t = a[22] ^ d2
bc1 = t<<6 | t>>(64-6) bc1 = bits.RotateLeft64(t, 6)
t = a[13] ^ d3 t = a[13] ^ d3
bc2 = t<<25 | t>>(64-25) bc2 = bits.RotateLeft64(t, 25)
t = a[4] ^ d4 t = a[4] ^ d4
bc3 = t<<8 | t>>(64-8) bc3 = bits.RotateLeft64(t, 8)
a[15] = bc0 ^ (bc2 &^ bc1) a[15] = bc0 ^ (bc2 &^ bc1)
a[6] = bc1 ^ (bc3 &^ bc2) a[6] = bc1 ^ (bc3 &^ bc2)
a[22] = bc2 ^ (bc4 &^ bc3) a[22] = bc2 ^ (bc4 &^ bc3)
@ -197,15 +199,15 @@ func keccakF1600(a *[25]uint64) {
a[4] = bc4 ^ (bc1 &^ bc0) a[4] = bc4 ^ (bc1 &^ bc0)
t = a[10] ^ d0 t = a[10] ^ d0
bc1 = t<<36 | t>>(64-36) bc1 = bits.RotateLeft64(t, 36)
t = a[1] ^ d1 t = a[1] ^ d1
bc2 = t<<10 | t>>(64-10) bc2 = bits.RotateLeft64(t, 10)
t = a[17] ^ d2 t = a[17] ^ d2
bc3 = t<<15 | t>>(64-15) bc3 = bits.RotateLeft64(t, 15)
t = a[8] ^ d3 t = a[8] ^ d3
bc4 = t<<56 | t>>(64-56) bc4 = bits.RotateLeft64(t, 56)
t = a[24] ^ d4 t = a[24] ^ d4
bc0 = t<<27 | t>>(64-27) bc0 = bits.RotateLeft64(t, 27)
a[10] = bc0 ^ (bc2 &^ bc1) a[10] = bc0 ^ (bc2 &^ bc1)
a[1] = bc1 ^ (bc3 &^ bc2) a[1] = bc1 ^ (bc3 &^ bc2)
a[17] = bc2 ^ (bc4 &^ bc3) a[17] = bc2 ^ (bc4 &^ bc3)
@ -213,15 +215,15 @@ func keccakF1600(a *[25]uint64) {
a[24] = bc4 ^ (bc1 &^ bc0) a[24] = bc4 ^ (bc1 &^ bc0)
t = a[5] ^ d0 t = a[5] ^ d0
bc3 = t<<41 | t>>(64-41) bc3 = bits.RotateLeft64(t, 41)
t = a[21] ^ d1 t = a[21] ^ d1
bc4 = t<<2 | t>>(64-2) bc4 = bits.RotateLeft64(t, 2)
t = a[12] ^ d2 t = a[12] ^ d2
bc0 = t<<62 | t>>(64-62) bc0 = bits.RotateLeft64(t, 62)
t = a[3] ^ d3 t = a[3] ^ d3
bc1 = t<<55 | t>>(64-55) bc1 = bits.RotateLeft64(t, 55)
t = a[19] ^ d4 t = a[19] ^ d4
bc2 = t<<39 | t>>(64-39) bc2 = bits.RotateLeft64(t, 39)
a[5] = bc0 ^ (bc2 &^ bc1) a[5] = bc0 ^ (bc2 &^ bc1)
a[21] = bc1 ^ (bc3 &^ bc2) a[21] = bc1 ^ (bc3 &^ bc2)
a[12] = bc2 ^ (bc4 &^ bc3) a[12] = bc2 ^ (bc4 &^ bc3)
@ -242,13 +244,13 @@ func keccakF1600(a *[25]uint64) {
bc0 = a[0] ^ d0 bc0 = a[0] ^ d0
t = a[11] ^ d1 t = a[11] ^ d1
bc1 = t<<44 | t>>(64-44) bc1 = bits.RotateLeft64(t, 44)
t = a[22] ^ d2 t = a[22] ^ d2
bc2 = t<<43 | t>>(64-43) bc2 = bits.RotateLeft64(t, 43)
t = a[8] ^ d3 t = a[8] ^ d3
bc3 = t<<21 | t>>(64-21) bc3 = bits.RotateLeft64(t, 21)
t = a[19] ^ d4 t = a[19] ^ d4
bc4 = t<<14 | t>>(64-14) bc4 = bits.RotateLeft64(t, 14)
a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2] a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2]
a[11] = bc1 ^ (bc3 &^ bc2) a[11] = bc1 ^ (bc3 &^ bc2)
a[22] = bc2 ^ (bc4 &^ bc3) a[22] = bc2 ^ (bc4 &^ bc3)
@ -256,15 +258,15 @@ func keccakF1600(a *[25]uint64) {
a[19] = bc4 ^ (bc1 &^ bc0) a[19] = bc4 ^ (bc1 &^ bc0)
t = a[15] ^ d0 t = a[15] ^ d0
bc2 = t<<3 | t>>(64-3) bc2 = bits.RotateLeft64(t, 3)
t = a[1] ^ d1 t = a[1] ^ d1
bc3 = t<<45 | t>>(64-45) bc3 = bits.RotateLeft64(t, 45)
t = a[12] ^ d2 t = a[12] ^ d2
bc4 = t<<61 | t>>(64-61) bc4 = bits.RotateLeft64(t, 61)
t = a[23] ^ d3 t = a[23] ^ d3
bc0 = t<<28 | t>>(64-28) bc0 = bits.RotateLeft64(t, 28)
t = a[9] ^ d4 t = a[9] ^ d4
bc1 = t<<20 | t>>(64-20) bc1 = bits.RotateLeft64(t, 20)
a[15] = bc0 ^ (bc2 &^ bc1) a[15] = bc0 ^ (bc2 &^ bc1)
a[1] = bc1 ^ (bc3 &^ bc2) a[1] = bc1 ^ (bc3 &^ bc2)
a[12] = bc2 ^ (bc4 &^ bc3) a[12] = bc2 ^ (bc4 &^ bc3)
@ -272,15 +274,15 @@ func keccakF1600(a *[25]uint64) {
a[9] = bc4 ^ (bc1 &^ bc0) a[9] = bc4 ^ (bc1 &^ bc0)
t = a[5] ^ d0 t = a[5] ^ d0
bc4 = t<<18 | t>>(64-18) bc4 = bits.RotateLeft64(t, 18)
t = a[16] ^ d1 t = a[16] ^ d1
bc0 = t<<1 | t>>(64-1) bc0 = bits.RotateLeft64(t, 1)
t = a[2] ^ d2 t = a[2] ^ d2
bc1 = t<<6 | t>>(64-6) bc1 = bits.RotateLeft64(t, 6)
t = a[13] ^ d3 t = a[13] ^ d3
bc2 = t<<25 | t>>(64-25) bc2 = bits.RotateLeft64(t, 25)
t = a[24] ^ d4 t = a[24] ^ d4
bc3 = t<<8 | t>>(64-8) bc3 = bits.RotateLeft64(t, 8)
a[5] = bc0 ^ (bc2 &^ bc1) a[5] = bc0 ^ (bc2 &^ bc1)
a[16] = bc1 ^ (bc3 &^ bc2) a[16] = bc1 ^ (bc3 &^ bc2)
a[2] = bc2 ^ (bc4 &^ bc3) a[2] = bc2 ^ (bc4 &^ bc3)
@ -288,15 +290,15 @@ func keccakF1600(a *[25]uint64) {
a[24] = bc4 ^ (bc1 &^ bc0) a[24] = bc4 ^ (bc1 &^ bc0)
t = a[20] ^ d0 t = a[20] ^ d0
bc1 = t<<36 | t>>(64-36) bc1 = bits.RotateLeft64(t, 36)
t = a[6] ^ d1 t = a[6] ^ d1
bc2 = t<<10 | t>>(64-10) bc2 = bits.RotateLeft64(t, 10)
t = a[17] ^ d2 t = a[17] ^ d2
bc3 = t<<15 | t>>(64-15) bc3 = bits.RotateLeft64(t, 15)
t = a[3] ^ d3 t = a[3] ^ d3
bc4 = t<<56 | t>>(64-56) bc4 = bits.RotateLeft64(t, 56)
t = a[14] ^ d4 t = a[14] ^ d4
bc0 = t<<27 | t>>(64-27) bc0 = bits.RotateLeft64(t, 27)
a[20] = bc0 ^ (bc2 &^ bc1) a[20] = bc0 ^ (bc2 &^ bc1)
a[6] = bc1 ^ (bc3 &^ bc2) a[6] = bc1 ^ (bc3 &^ bc2)
a[17] = bc2 ^ (bc4 &^ bc3) a[17] = bc2 ^ (bc4 &^ bc3)
@ -304,15 +306,15 @@ func keccakF1600(a *[25]uint64) {
a[14] = bc4 ^ (bc1 &^ bc0) a[14] = bc4 ^ (bc1 &^ bc0)
t = a[10] ^ d0 t = a[10] ^ d0
bc3 = t<<41 | t>>(64-41) bc3 = bits.RotateLeft64(t, 41)
t = a[21] ^ d1 t = a[21] ^ d1
bc4 = t<<2 | t>>(64-2) bc4 = bits.RotateLeft64(t, 2)
t = a[7] ^ d2 t = a[7] ^ d2
bc0 = t<<62 | t>>(64-62) bc0 = bits.RotateLeft64(t, 62)
t = a[18] ^ d3 t = a[18] ^ d3
bc1 = t<<55 | t>>(64-55) bc1 = bits.RotateLeft64(t, 55)
t = a[4] ^ d4 t = a[4] ^ d4
bc2 = t<<39 | t>>(64-39) bc2 = bits.RotateLeft64(t, 39)
a[10] = bc0 ^ (bc2 &^ bc1) a[10] = bc0 ^ (bc2 &^ bc1)
a[21] = bc1 ^ (bc3 &^ bc2) a[21] = bc1 ^ (bc3 &^ bc2)
a[7] = bc2 ^ (bc4 &^ bc3) a[7] = bc2 ^ (bc4 &^ bc3)
@ -333,13 +335,13 @@ func keccakF1600(a *[25]uint64) {
bc0 = a[0] ^ d0 bc0 = a[0] ^ d0
t = a[1] ^ d1 t = a[1] ^ d1
bc1 = t<<44 | t>>(64-44) bc1 = bits.RotateLeft64(t, 44)
t = a[2] ^ d2 t = a[2] ^ d2
bc2 = t<<43 | t>>(64-43) bc2 = bits.RotateLeft64(t, 43)
t = a[3] ^ d3 t = a[3] ^ d3
bc3 = t<<21 | t>>(64-21) bc3 = bits.RotateLeft64(t, 21)
t = a[4] ^ d4 t = a[4] ^ d4
bc4 = t<<14 | t>>(64-14) bc4 = bits.RotateLeft64(t, 14)
a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3] a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3]
a[1] = bc1 ^ (bc3 &^ bc2) a[1] = bc1 ^ (bc3 &^ bc2)
a[2] = bc2 ^ (bc4 &^ bc3) a[2] = bc2 ^ (bc4 &^ bc3)
@ -347,15 +349,15 @@ func keccakF1600(a *[25]uint64) {
a[4] = bc4 ^ (bc1 &^ bc0) a[4] = bc4 ^ (bc1 &^ bc0)
t = a[5] ^ d0 t = a[5] ^ d0
bc2 = t<<3 | t>>(64-3) bc2 = bits.RotateLeft64(t, 3)
t = a[6] ^ d1 t = a[6] ^ d1
bc3 = t<<45 | t>>(64-45) bc3 = bits.RotateLeft64(t, 45)
t = a[7] ^ d2 t = a[7] ^ d2
bc4 = t<<61 | t>>(64-61) bc4 = bits.RotateLeft64(t, 61)
t = a[8] ^ d3 t = a[8] ^ d3
bc0 = t<<28 | t>>(64-28) bc0 = bits.RotateLeft64(t, 28)
t = a[9] ^ d4 t = a[9] ^ d4
bc1 = t<<20 | t>>(64-20) bc1 = bits.RotateLeft64(t, 20)
a[5] = bc0 ^ (bc2 &^ bc1) a[5] = bc0 ^ (bc2 &^ bc1)
a[6] = bc1 ^ (bc3 &^ bc2) a[6] = bc1 ^ (bc3 &^ bc2)
a[7] = bc2 ^ (bc4 &^ bc3) a[7] = bc2 ^ (bc4 &^ bc3)
@ -363,15 +365,15 @@ func keccakF1600(a *[25]uint64) {
a[9] = bc4 ^ (bc1 &^ bc0) a[9] = bc4 ^ (bc1 &^ bc0)
t = a[10] ^ d0 t = a[10] ^ d0
bc4 = t<<18 | t>>(64-18) bc4 = bits.RotateLeft64(t, 18)
t = a[11] ^ d1 t = a[11] ^ d1
bc0 = t<<1 | t>>(64-1) bc0 = bits.RotateLeft64(t, 1)
t = a[12] ^ d2 t = a[12] ^ d2
bc1 = t<<6 | t>>(64-6) bc1 = bits.RotateLeft64(t, 6)
t = a[13] ^ d3 t = a[13] ^ d3
bc2 = t<<25 | t>>(64-25) bc2 = bits.RotateLeft64(t, 25)
t = a[14] ^ d4 t = a[14] ^ d4
bc3 = t<<8 | t>>(64-8) bc3 = bits.RotateLeft64(t, 8)
a[10] = bc0 ^ (bc2 &^ bc1) a[10] = bc0 ^ (bc2 &^ bc1)
a[11] = bc1 ^ (bc3 &^ bc2) a[11] = bc1 ^ (bc3 &^ bc2)
a[12] = bc2 ^ (bc4 &^ bc3) a[12] = bc2 ^ (bc4 &^ bc3)
@ -379,15 +381,15 @@ func keccakF1600(a *[25]uint64) {
a[14] = bc4 ^ (bc1 &^ bc0) a[14] = bc4 ^ (bc1 &^ bc0)
t = a[15] ^ d0 t = a[15] ^ d0
bc1 = t<<36 | t>>(64-36) bc1 = bits.RotateLeft64(t, 36)
t = a[16] ^ d1 t = a[16] ^ d1
bc2 = t<<10 | t>>(64-10) bc2 = bits.RotateLeft64(t, 10)
t = a[17] ^ d2 t = a[17] ^ d2
bc3 = t<<15 | t>>(64-15) bc3 = bits.RotateLeft64(t, 15)
t = a[18] ^ d3 t = a[18] ^ d3
bc4 = t<<56 | t>>(64-56) bc4 = bits.RotateLeft64(t, 56)
t = a[19] ^ d4 t = a[19] ^ d4
bc0 = t<<27 | t>>(64-27) bc0 = bits.RotateLeft64(t, 27)
a[15] = bc0 ^ (bc2 &^ bc1) a[15] = bc0 ^ (bc2 &^ bc1)
a[16] = bc1 ^ (bc3 &^ bc2) a[16] = bc1 ^ (bc3 &^ bc2)
a[17] = bc2 ^ (bc4 &^ bc3) a[17] = bc2 ^ (bc4 &^ bc3)
@ -395,15 +397,15 @@ func keccakF1600(a *[25]uint64) {
a[19] = bc4 ^ (bc1 &^ bc0) a[19] = bc4 ^ (bc1 &^ bc0)
t = a[20] ^ d0 t = a[20] ^ d0
bc3 = t<<41 | t>>(64-41) bc3 = bits.RotateLeft64(t, 41)
t = a[21] ^ d1 t = a[21] ^ d1
bc4 = t<<2 | t>>(64-2) bc4 = bits.RotateLeft64(t, 2)
t = a[22] ^ d2 t = a[22] ^ d2
bc0 = t<<62 | t>>(64-62) bc0 = bits.RotateLeft64(t, 62)
t = a[23] ^ d3 t = a[23] ^ d3
bc1 = t<<55 | t>>(64-55) bc1 = bits.RotateLeft64(t, 55)
t = a[24] ^ d4 t = a[24] ^ d4
bc2 = t<<39 | t>>(64-39) bc2 = bits.RotateLeft64(t, 39)
a[20] = bc0 ^ (bc2 &^ bc1) a[20] = bc0 ^ (bc2 &^ bc1)
a[21] = bc1 ^ (bc3 &^ bc2) a[21] = bc1 ^ (bc3 &^ bc2)
a[22] = bc2 ^ (bc4 &^ bc3) a[22] = bc2 ^ (bc4 &^ bc3)

3
vendor/golang.org/x/sys/AUTHORS generated vendored
View File

@ -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.

View File

@ -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.

View File

@ -46,6 +46,7 @@ func hostByteOrder() byteOrder {
case "386", "amd64", "amd64p32", case "386", "amd64", "amd64p32",
"alpha", "alpha",
"arm", "arm64", "arm", "arm64",
"loong64",
"mipsle", "mips64le", "mips64p32le", "mipsle", "mips64le", "mips64p32le",
"nios2", "nios2",
"ppc64le", "ppc64le",

5
vendor/golang.org/x/sys/cpu/cpu.go generated vendored
View File

@ -56,6 +56,7 @@ var X86 struct {
HasAVX512BF16 bool // Advanced vector extension 512 BFloat16 Instructions HasAVX512BF16 bool // Advanced vector extension 512 BFloat16 Instructions
HasBMI1 bool // Bit manipulation instruction set 1 HasBMI1 bool // Bit manipulation instruction set 1
HasBMI2 bool // Bit manipulation instruction set 2 HasBMI2 bool // Bit manipulation instruction set 2
HasCX16 bool // Compare and exchange 16 Bytes
HasERMS bool // Enhanced REP for MOVSB and STOSB HasERMS bool // Enhanced REP for MOVSB and STOSB
HasFMA bool // Fused-multiply-add instructions HasFMA bool // Fused-multiply-add instructions
HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers. HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers.
@ -105,8 +106,8 @@ var ARM64 struct {
// ARM contains the supported CPU features of the current ARM (32-bit) platform. // ARM contains the supported CPU features of the current ARM (32-bit) platform.
// All feature flags are false if: // All feature flags are false if:
// 1. the current platform is not arm, or // 1. the current platform is not arm, or
// 2. the current operating system is not Linux. // 2. the current operating system is not Linux.
var ARM struct { var ARM struct {
_ CacheLinePad _ CacheLinePad
HasSWP bool // SWP instruction support HasSWP bool // SWP instruction support

View File

@ -6,7 +6,10 @@ package cpu
import "runtime" 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() { func initOptions() {
options = []option{ options = []option{
@ -41,13 +44,10 @@ func archInit() {
switch runtime.GOOS { switch runtime.GOOS {
case "freebsd": case "freebsd":
readARM64Registers() readARM64Registers()
case "linux", "netbsd": case "linux", "netbsd", "openbsd":
doinit() doinit()
default: default:
// Most platforms don't seem to allow reading these registers. // Many platforms don't seem to allow reading these registers.
//
// OpenBSD:
// See https://golang.org/issue/31746
setMinimalFeatures() setMinimalFeatures()
} }
} }

View File

@ -15,7 +15,3 @@ 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_x86.s for gc compiler
// and in cpu_gccgo.c for gccgo. // and in cpu_gccgo.c for gccgo.
func xgetbv() (eax, edx uint32) func xgetbv() (eax, edx uint32)
// darwinSupportsAVX512 is implemented in cpu_x86.s for gc compiler
// and in cpu_gccgo_x86.go for gccgo.
func darwinSupportsAVX512() bool

View File

@ -7,6 +7,7 @@
#include <cpuid.h> #include <cpuid.h>
#include <stdint.h> #include <stdint.h>
#include <x86intrin.h>
// Need to wrap __get_cpuid_count because it's declared as static. // Need to wrap __get_cpuid_count because it's declared as static.
int int
@ -17,27 +18,21 @@ gccgoGetCpuidCount(uint32_t leaf, uint32_t subleaf,
return __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); 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) // xgetbv reads the contents of an XCR (Extended Control Register)
// specified in the ECX register into registers EDX:EAX. // specified in the ECX register into registers EDX:EAX.
// Currently, the only supported value for XCR is 0. // Currently, the only supported value for XCR is 0.
//
// TODO: Replace with a better alternative:
//
// #include <xsaveintrin.h>
//
// #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 void
gccgoXgetbv(uint32_t *eax, uint32_t *edx) gccgoXgetbv(uint32_t *eax, uint32_t *edx)
{ {
__asm(" xorl %%ecx, %%ecx\n" uint64_t v = _xgetbv(0);
" xgetbv" *eax = v & 0xffffffff;
: "=a"(*eax), "=d"(*edx)); *edx = v >> 32;
} }
#pragma clang attribute pop
#pragma GCC pop_options

View File

@ -4,6 +4,11 @@
package cpu package cpu
import (
"strings"
"syscall"
)
// HWCAP/HWCAP2 bits. These are exposed by Linux. // HWCAP/HWCAP2 bits. These are exposed by Linux.
const ( const (
hwcap_FP = 1 << 0 hwcap_FP = 1 << 0
@ -32,10 +37,45 @@ const (
hwcap_ASIMDFHM = 1 << 23 hwcap_ASIMDFHM = 1 << 23
) )
// 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() { func doinit() {
if err := readHWCAP(); err != nil { if err := readHWCAP(); err != nil {
// failed to read /proc/self/auxv, try reading registers directly // We failed to read /proc/self/auxv. This can happen if the binary has
readARM64Registers() // 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 return
} }

13
vendor/golang.org/x/sys/cpu/cpu_loong64.go generated vendored Normal file
View File

@ -0,0 +1,13 @@
// 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
// +build loong64
package cpu
const cacheLineSize = 64
func initOptions() {
}

65
vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go generated vendored Normal file
View File

@ -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
}

11
vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.s generated vendored Normal file
View File

@ -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)

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !linux && !netbsd && arm64 //go:build !linux && !netbsd && !openbsd && arm64
// +build !linux,!netbsd,arm64 // +build !linux,!netbsd,!openbsd,arm64
package cpu package cpu

15
vendor/golang.org/x/sys/cpu/cpu_other_ppc64x.go generated vendored Normal file
View File

@ -0,0 +1,15 @@
// 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)
// +build !aix
// +build !linux
// +build ppc64 ppc64le
package cpu
func archInit() {
PPC64.IsPOWER8 = true
Initialized = true
}

12
vendor/golang.org/x/sys/cpu/cpu_other_riscv64.go generated vendored Normal file
View File

@ -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 && riscv64
// +build !linux,riscv64
package cpu
func archInit() {
Initialized = true
}

View File

@ -39,6 +39,7 @@ func initOptions() {
{Name: "avx512bf16", Feature: &X86.HasAVX512BF16}, {Name: "avx512bf16", Feature: &X86.HasAVX512BF16},
{Name: "bmi1", Feature: &X86.HasBMI1}, {Name: "bmi1", Feature: &X86.HasBMI1},
{Name: "bmi2", Feature: &X86.HasBMI2}, {Name: "bmi2", Feature: &X86.HasBMI2},
{Name: "cx16", Feature: &X86.HasCX16},
{Name: "erms", Feature: &X86.HasERMS}, {Name: "erms", Feature: &X86.HasERMS},
{Name: "fma", Feature: &X86.HasFMA}, {Name: "fma", Feature: &X86.HasFMA},
{Name: "osxsave", Feature: &X86.HasOSXSAVE}, {Name: "osxsave", Feature: &X86.HasOSXSAVE},
@ -73,6 +74,7 @@ func archInit() {
X86.HasPCLMULQDQ = isSet(1, ecx1) X86.HasPCLMULQDQ = isSet(1, ecx1)
X86.HasSSSE3 = isSet(9, ecx1) X86.HasSSSE3 = isSet(9, ecx1)
X86.HasFMA = isSet(12, ecx1) X86.HasFMA = isSet(12, ecx1)
X86.HasCX16 = isSet(13, ecx1)
X86.HasSSE41 = isSet(19, ecx1) X86.HasSSE41 = isSet(19, ecx1)
X86.HasSSE42 = isSet(20, ecx1) X86.HasSSE42 = isSet(20, ecx1)
X86.HasPOPCNT = isSet(23, ecx1) X86.HasPOPCNT = isSet(23, ecx1)
@ -88,9 +90,10 @@ func archInit() {
osSupportsAVX = isSet(1, eax) && isSet(2, eax) osSupportsAVX = isSet(1, eax) && isSet(2, eax)
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
// Check darwin commpage for AVX512 support. Necessary because: // Darwin doesn't save/restore AVX-512 mask registers correctly across signal handlers.
// https://github.com/apple/darwin-xnu/blob/0a798f6738bc1db01281fc08ae024145e84df927/osfmk/i386/fpu.c#L175-L201 // Since users can't rely on mask register contents, let's not advertise AVX-512 support.
osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512() // See issue 49233.
osSupportsAVX512 = false
} else { } else {
// Check if OPMASK and ZMM registers have OS support. // Check if OPMASK and ZMM registers have OS support.
osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax) osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax)

View File

@ -26,27 +26,3 @@ TEXT ·xgetbv(SB),NOSPLIT,$0-8
MOVL AX, eax+0(FP) MOVL AX, eax+0(FP)
MOVL DX, edx+4(FP) MOVL DX, edx+4(FP)
RET RET
// func darwinSupportsAVX512() bool
TEXT ·darwinSupportsAVX512(SB), NOSPLIT, $0-1
MOVB $0, ret+0(FP) // default to false
#ifdef GOOS_darwin // return if not darwin
#ifdef GOARCH_amd64 // return if not amd64
// These values from:
// https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/osfmk/i386/cpu_capabilities.h
#define commpage64_base_address 0x00007fffffe00000
#define commpage64_cpu_capabilities64 (commpage64_base_address+0x010)
#define commpage64_version (commpage64_base_address+0x01E)
#define hasAVX512F 0x0000004000000000
MOVQ $commpage64_version, BX
CMPW (BX), $13 // cpu_capabilities64 undefined in versions < 13
JL no_avx512
MOVQ $commpage64_cpu_capabilities64, BX
MOVQ $hasAVX512F, CX
TESTQ (BX), CX
JZ no_avx512
MOVB $1, ret+0(FP)
no_avx512:
#endif
#endif
RET

43
vendor/golang.org/x/sys/cpu/parse.go generated vendored Normal file
View File

@ -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 := 0; i < len(rel); i++ {
if rel[i] == '-' || rel[i] == '+' {
rel = rel[:i]
break
}
}
next := func() (int, bool) {
for i := 0; i < len(rel); i++ {
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
}

54
vendor/golang.org/x/sys/cpu/proc_cpuinfo_linux.go generated vendored Normal file
View File

@ -0,0 +1,54 @@
// 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
// +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
}

View File

@ -5,7 +5,7 @@
// Recreate a getsystemcfg syscall handler instead of // Recreate a getsystemcfg syscall handler instead of
// using the one provided by x/sys/unix to avoid having // using the one provided by x/sys/unix to avoid having
// the dependency between them. (See golang.org/issue/32102) // the dependency between them. (See golang.org/issue/32102)
// Morever, this file will be used during the building of // Moreover, this file will be used during the building of
// gccgo's libgo and thus must not used a CGo method. // gccgo's libgo and thus must not used a CGo method.
//go:build aix && gccgo //go:build aix && gccgo

View File

@ -126,7 +126,7 @@ errors=$(
signals=$( signals=$(
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags | echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' | awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' | grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT' |
sort sort
) )
@ -136,7 +136,7 @@ echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
sort >_error.grep sort >_error.grep
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags | echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' | awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' | grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT' |
sort >_signal.grep sort >_signal.grep
echo '// mkerrors.sh' "$@" echo '// mkerrors.sh' "$@"

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build go1.5
// +build go1.5 // +build go1.5
package plan9 package plan9

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build !go1.5
// +build !go1.5 // +build !go1.5
package plan9 package plan9

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build plan9 && race
// +build plan9,race // +build plan9,race
package plan9 package plan9

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build plan9 && !race
// +build plan9,!race // +build plan9,!race
package plan9 package plan9

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build plan9
// +build plan9 // +build plan9
package plan9 package plan9

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build plan9
// +build plan9 // +build plan9
// Package plan9 contains an interface to the low-level operating system // Package plan9 contains an interface to the low-level operating system
@ -28,8 +29,6 @@ import (
"bytes" "bytes"
"strings" "strings"
"unsafe" "unsafe"
"golang.org/x/sys/internal/unsafeheader"
) )
// ByteSliceFromString returns a NUL-terminated slice of bytes // ByteSliceFromString returns a NUL-terminated slice of bytes
@ -81,13 +80,7 @@ func BytePtrToString(p *byte) string {
ptr = unsafe.Pointer(uintptr(ptr) + 1) ptr = unsafe.Pointer(uintptr(ptr) + 1)
} }
var s []byte return string(unsafe.Slice(p, n))
h := (*unsafeheader.Slice)(unsafe.Pointer(&s))
h.Data = unsafe.Pointer(p)
h.Len = n
h.Cap = n
return string(s)
} }
// Single-word zero for use when we need a valid pointer to 0 bytes. // Single-word zero for use when we need a valid pointer to 0 bytes.
@ -112,5 +105,6 @@ func (tv *Timeval) Nano() int64 {
// use is a no-op, but the compiler cannot see that it is. // use is a no-op, but the compiler cannot see that it is.
// Calling use(p) ensures that p is kept live until that point. // Calling use(p) ensures that p is kept live until that point.
//
//go:noescape //go:noescape
func use(p unsafe.Pointer) func use(p unsafe.Pointer)

View File

@ -115,6 +115,7 @@ func Write(fd int, p []byte) (n int, err error) {
var ioSync int64 var ioSync int64
//sys fd2path(fd int, buf []byte) (err error) //sys fd2path(fd int, buf []byte) (err error)
func Fd2path(fd int) (path string, err error) { func Fd2path(fd int) (path string, err error) {
var buf [512]byte var buf [512]byte
@ -126,14 +127,17 @@ func Fd2path(fd int) (path string, err error) {
} }
//sys pipe(p *[2]int32) (err error) //sys pipe(p *[2]int32) (err error)
func Pipe(p []int) (err error) { func Pipe(p []int) (err error) {
if len(p) != 2 { if len(p) != 2 {
return syscall.ErrorString("bad arg in system call") return syscall.ErrorString("bad arg in system call")
} }
var pp [2]int32 var pp [2]int32
err = pipe(&pp) err = pipe(&pp)
p[0] = int(pp[0]) if err == nil {
p[1] = int(pp[1]) p[0] = int(pp[0])
p[1] = int(pp[1])
}
return return
} }
@ -178,6 +182,7 @@ func (w Waitmsg) ExitStatus() int {
} }
//sys await(s []byte) (n int, err error) //sys await(s []byte) (n int, err error)
func Await(w *Waitmsg) (err error) { func Await(w *Waitmsg) (err error) {
var buf [512]byte var buf [512]byte
var f [5][]byte var f [5][]byte
@ -299,42 +304,49 @@ func Getgroups() (gids []int, err error) {
} }
//sys open(path string, mode int) (fd int, err error) //sys open(path string, mode int) (fd int, err error)
func Open(path string, mode int) (fd int, err error) { func Open(path string, mode int) (fd int, err error) {
fixwd() fixwd()
return open(path, mode) return open(path, mode)
} }
//sys create(path string, mode int, perm uint32) (fd int, err error) //sys create(path string, mode int, perm uint32) (fd int, err error)
func Create(path string, mode int, perm uint32) (fd int, err error) { func Create(path string, mode int, perm uint32) (fd int, err error) {
fixwd() fixwd()
return create(path, mode, perm) return create(path, mode, perm)
} }
//sys remove(path string) (err error) //sys remove(path string) (err error)
func Remove(path string) error { func Remove(path string) error {
fixwd() fixwd()
return remove(path) return remove(path)
} }
//sys stat(path string, edir []byte) (n int, err error) //sys stat(path string, edir []byte) (n int, err error)
func Stat(path string, edir []byte) (n int, err error) { func Stat(path string, edir []byte) (n int, err error) {
fixwd() fixwd()
return stat(path, edir) return stat(path, edir)
} }
//sys bind(name string, old string, flag int) (err error) //sys bind(name string, old string, flag int) (err error)
func Bind(name string, old string, flag int) (err error) { func Bind(name string, old string, flag int) (err error) {
fixwd() fixwd()
return bind(name, old, flag) return bind(name, old, flag)
} }
//sys mount(fd int, afd int, old string, flag int, aname string) (err error) //sys mount(fd int, afd int, old string, flag int, aname string) (err error)
func Mount(fd int, afd int, old string, flag int, aname string) (err error) { func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
fixwd() fixwd()
return mount(fd, afd, old, flag, aname) return mount(fd, afd, old, flag, aname)
} }
//sys wstat(path string, edir []byte) (err error) //sys wstat(path string, edir []byte) (err error)
func Wstat(path string, edir []byte) (err error) { func Wstat(path string, edir []byte) (err error) {
fixwd() fixwd()
return wstat(path, edir) return wstat(path, edir)

View File

@ -1,6 +1,7 @@
// go run mksyscall.go -l32 -plan9 -tags plan9,386 syscall_plan9.go // go run mksyscall.go -l32 -plan9 -tags plan9,386 syscall_plan9.go
// Code generated by the command above; see README.md. DO NOT EDIT. // Code generated by the command above; see README.md. DO NOT EDIT.
//go:build plan9 && 386
// +build plan9,386 // +build plan9,386
package plan9 package plan9

View File

@ -1,6 +1,7 @@
// go run mksyscall.go -l32 -plan9 -tags plan9,amd64 syscall_plan9.go // go run mksyscall.go -l32 -plan9 -tags plan9,amd64 syscall_plan9.go
// Code generated by the command above; see README.md. DO NOT EDIT. // Code generated by the command above; see README.md. DO NOT EDIT.
//go:build plan9 && amd64
// +build plan9,amd64 // +build plan9,amd64
package plan9 package plan9

View File

@ -1,6 +1,7 @@
// go run mksyscall.go -l32 -plan9 -tags plan9,arm syscall_plan9.go // go run mksyscall.go -l32 -plan9 -tags plan9,arm syscall_plan9.go
// Code generated by the command above; see README.md. DO NOT EDIT. // Code generated by the command above; see README.md. DO NOT EDIT.
//go:build plan9 && arm
// +build plan9,arm // +build plan9,arm
package plan9 package plan9

View File

@ -149,7 +149,7 @@ 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 Then, edit the regex (if necessary) to match the desired constant. Avoid making
the regex too broad to avoid matching unintended constants. 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 This program is used to extract duplicate const, func, and type declarations
from the generated architecture-specific files listed below, and merge these from the generated architecture-specific files listed below, and merge these

31
vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s generated vendored Normal file
View File

@ -0,0 +1,31 @@
// 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 (darwin || freebsd || netbsd || openbsd) && gc
// +build darwin freebsd netbsd openbsd
// +build gc
#include "textflag.h"
//
// System call support for ppc64, 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)

29
vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s generated vendored Normal file
View File

@ -0,0 +1,29 @@
// 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 || freebsd || netbsd || openbsd) && gc
// +build darwin freebsd netbsd openbsd
// +build gc
#include "textflag.h"
// System call support for RISCV64 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)

54
vendor/golang.org/x/sys/unix/asm_linux_loong64.s generated vendored Normal file
View File

@ -0,0 +1,54 @@
// 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
// +build linux
// +build loong64
// +build 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

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
package unix package unix

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// //
//go:build 386 || amd64 || amd64p32 || alpha || arm || arm64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh //go:build 386 || amd64 || amd64p32 || alpha || arm || arm64 || loong64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh
// +build 386 amd64 amd64p32 alpha arm arm64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh // +build 386 amd64 amd64p32 alpha arm arm64 loong64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh
package unix package unix

View File

@ -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
)

View File

@ -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
)

View File

@ -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
)

View File

@ -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
)

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build gccgo && !aix //go:build gccgo && !aix && !hurd
// +build gccgo,!aix // +build gccgo,!aix,!hurd
package unix package unix

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build gccgo // +build gccgo,!hurd
// +build !aix // +build !aix,!hurd
#include <errno.h> #include <errno.h>
#include <stdint.h> #include <stdint.h>

142
vendor/golang.org/x/sys/unix/ifreq_linux.go generated vendored Normal file
View File

@ -0,0 +1,142 @@
// 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
// +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() {
for i := range ifr.raw.Ifru {
ifr.raw.Ifru[i] = 0
}
}
// 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,
}
}

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris //go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
package unix package unix

View File

@ -4,10 +4,7 @@
package unix package unix
import ( import "unsafe"
"runtime"
"unsafe"
)
// IoctlRetInt performs an ioctl operation specified by req on a device // IoctlRetInt performs an ioctl operation specified by req on a device
// associated with opened file descriptor fd, and returns a non-negative // associated with opened file descriptor fd, and returns a non-negative
@ -22,56 +19,42 @@ func IoctlRetInt(fd int, req uint) (int, error) {
func IoctlGetUint32(fd int, req uint) (uint32, error) { func IoctlGetUint32(fd int, req uint) (uint32, error) {
var value uint32 var value uint32
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) err := ioctlPtr(fd, req, unsafe.Pointer(&value))
return value, err return value, err
} }
func IoctlGetRTCTime(fd int) (*RTCTime, error) { func IoctlGetRTCTime(fd int) (*RTCTime, error) {
var value RTCTime var value RTCTime
err := ioctl(fd, RTC_RD_TIME, uintptr(unsafe.Pointer(&value))) err := ioctlPtr(fd, RTC_RD_TIME, unsafe.Pointer(&value))
return &value, err return &value, err
} }
func IoctlSetRTCTime(fd int, value *RTCTime) error { func IoctlSetRTCTime(fd int, value *RTCTime) error {
err := ioctl(fd, RTC_SET_TIME, uintptr(unsafe.Pointer(value))) return ioctlPtr(fd, RTC_SET_TIME, unsafe.Pointer(value))
runtime.KeepAlive(value)
return err
} }
func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) { func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) {
var value RTCWkAlrm var value RTCWkAlrm
err := ioctl(fd, RTC_WKALM_RD, uintptr(unsafe.Pointer(&value))) err := ioctlPtr(fd, RTC_WKALM_RD, unsafe.Pointer(&value))
return &value, err return &value, err
} }
func IoctlSetRTCWkAlrm(fd int, value *RTCWkAlrm) error { func IoctlSetRTCWkAlrm(fd int, value *RTCWkAlrm) error {
err := ioctl(fd, RTC_WKALM_SET, uintptr(unsafe.Pointer(value))) return ioctlPtr(fd, RTC_WKALM_SET, unsafe.Pointer(value))
runtime.KeepAlive(value)
return err
}
type ifreqEthtool struct {
name [IFNAMSIZ]byte
data unsafe.Pointer
} }
// IoctlGetEthtoolDrvinfo fetches ethtool driver information for the network // IoctlGetEthtoolDrvinfo fetches ethtool driver information for the network
// device specified by ifname. // device specified by ifname.
func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) { func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) {
// Leave room for terminating NULL byte. ifr, err := NewIfreq(ifname)
if len(ifname) >= IFNAMSIZ { if err != nil {
return nil, EINVAL return nil, err
} }
value := EthtoolDrvinfo{ value := EthtoolDrvinfo{Cmd: ETHTOOL_GDRVINFO}
Cmd: ETHTOOL_GDRVINFO, ifrd := ifr.withData(unsafe.Pointer(&value))
}
ifreq := ifreqEthtool{ err = ioctlIfreqData(fd, SIOCETHTOOL, &ifrd)
data: unsafe.Pointer(&value),
}
copy(ifreq.name[:], ifname)
err := ioctl(fd, SIOCETHTOOL, uintptr(unsafe.Pointer(&ifreq)))
runtime.KeepAlive(ifreq)
return &value, err return &value, err
} }
@ -80,7 +63,7 @@ func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) {
// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html. // https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) { func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) {
var value WatchdogInfo var value WatchdogInfo
err := ioctl(fd, WDIOC_GETSUPPORT, uintptr(unsafe.Pointer(&value))) err := ioctlPtr(fd, WDIOC_GETSUPPORT, unsafe.Pointer(&value))
return &value, err return &value, err
} }
@ -88,6 +71,7 @@ func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) {
// more information, see: // more information, see:
// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html. // https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
func IoctlWatchdogKeepalive(fd int) error { 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) return ioctl(fd, WDIOC_KEEPALIVE, 0)
} }
@ -95,9 +79,7 @@ func IoctlWatchdogKeepalive(fd int) error {
// range of data conveyed in value to the file associated with the file // range of data conveyed in value to the file associated with the file
// descriptor destFd. See the ioctl_ficlonerange(2) man page for details. // descriptor destFd. See the ioctl_ficlonerange(2) man page for details.
func IoctlFileCloneRange(destFd int, value *FileCloneRange) error { func IoctlFileCloneRange(destFd int, value *FileCloneRange) error {
err := ioctl(destFd, FICLONERANGE, uintptr(unsafe.Pointer(value))) return ioctlPtr(destFd, FICLONERANGE, unsafe.Pointer(value))
runtime.KeepAlive(value)
return err
} }
// IoctlFileClone performs an FICLONE ioctl operation to clone the entire file // IoctlFileClone performs an FICLONE ioctl operation to clone the entire file
@ -148,7 +130,7 @@ func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error {
rawinfo.Reserved = value.Info[i].Reserved rawinfo.Reserved = value.Info[i].Reserved
} }
err := ioctl(srcFd, FIDEDUPERANGE, uintptr(unsafe.Pointer(&buf[0]))) err := ioctlPtr(srcFd, FIDEDUPERANGE, unsafe.Pointer(&buf[0]))
// Output // Output
for i := range value.Info { for i := range value.Info {
@ -166,31 +148,86 @@ func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error {
} }
func IoctlHIDGetDesc(fd int, value *HIDRawReportDescriptor) error { func IoctlHIDGetDesc(fd int, value *HIDRawReportDescriptor) error {
err := ioctl(fd, HIDIOCGRDESC, uintptr(unsafe.Pointer(value))) return ioctlPtr(fd, HIDIOCGRDESC, unsafe.Pointer(value))
runtime.KeepAlive(value)
return err
} }
func IoctlHIDGetRawInfo(fd int) (*HIDRawDevInfo, error) { func IoctlHIDGetRawInfo(fd int) (*HIDRawDevInfo, error) {
var value HIDRawDevInfo var value HIDRawDevInfo
err := ioctl(fd, HIDIOCGRAWINFO, uintptr(unsafe.Pointer(&value))) err := ioctlPtr(fd, HIDIOCGRAWINFO, unsafe.Pointer(&value))
return &value, err return &value, err
} }
func IoctlHIDGetRawName(fd int) (string, error) { func IoctlHIDGetRawName(fd int) (string, error) {
var value [_HIDIOCGRAWNAME_LEN]byte var value [_HIDIOCGRAWNAME_LEN]byte
err := ioctl(fd, _HIDIOCGRAWNAME, uintptr(unsafe.Pointer(&value[0]))) err := ioctlPtr(fd, _HIDIOCGRAWNAME, unsafe.Pointer(&value[0]))
return ByteSliceToString(value[:]), err return ByteSliceToString(value[:]), err
} }
func IoctlHIDGetRawPhys(fd int) (string, error) { func IoctlHIDGetRawPhys(fd int) (string, error) {
var value [_HIDIOCGRAWPHYS_LEN]byte var value [_HIDIOCGRAWPHYS_LEN]byte
err := ioctl(fd, _HIDIOCGRAWPHYS, uintptr(unsafe.Pointer(&value[0]))) err := ioctlPtr(fd, _HIDIOCGRAWPHYS, unsafe.Pointer(&value[0]))
return ByteSliceToString(value[:]), err return ByteSliceToString(value[:]), err
} }
func IoctlHIDGetRawUniq(fd int) (string, error) { func IoctlHIDGetRawUniq(fd int) (string, error) {
var value [_HIDIOCGRAWUNIQ_LEN]byte var value [_HIDIOCGRAWUNIQ_LEN]byte
err := ioctl(fd, _HIDIOCGRAWUNIQ, uintptr(unsafe.Pointer(&value[0]))) err := ioctlPtr(fd, _HIDIOCGRAWUNIQ, unsafe.Pointer(&value[0]))
return ByteSliceToString(value[:]), err 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))
}

View File

@ -50,7 +50,7 @@ if [[ "$GOOS" = "linux" ]]; then
# Use the Docker-based build system # Use the Docker-based build system
# Files generated through docker (use $cmd so you can Ctl-C the build or run) # Files generated through docker (use $cmd so you can Ctl-C the build or run)
$cmd docker build --tag generate:$GOOS $GOOS $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")/.." && /bin/pwd):/build generate:$GOOS
exit exit
fi fi
@ -73,12 +73,12 @@ aix_ppc64)
darwin_amd64) darwin_amd64)
mkerrors="$mkerrors -m64" mkerrors="$mkerrors -m64"
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go" mkasm="go run mkasm.go"
;; ;;
darwin_arm64) darwin_arm64)
mkerrors="$mkerrors -m64" mkerrors="$mkerrors -m64"
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go" mkasm="go run mkasm.go"
;; ;;
dragonfly_amd64) dragonfly_amd64)
mkerrors="$mkerrors -m64" mkerrors="$mkerrors -m64"
@ -89,25 +89,30 @@ dragonfly_amd64)
freebsd_386) freebsd_386)
mkerrors="$mkerrors -m32" mkerrors="$mkerrors -m32"
mksyscall="go run mksyscall.go -l32" 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" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;; ;;
freebsd_amd64) freebsd_amd64)
mkerrors="$mkerrors -m64" 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" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;; ;;
freebsd_arm) freebsd_arm)
mkerrors="$mkerrors" mkerrors="$mkerrors"
mksyscall="go run mksyscall.go -l32 -arm" 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 # Let the type of C char be signed for making the bare syscall
# API consistent across platforms. # API consistent across platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;; ;;
freebsd_arm64) freebsd_arm64)
mkerrors="$mkerrors -m64" 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" mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;; ;;
netbsd_386) netbsd_386)
@ -137,42 +142,60 @@ netbsd_arm64)
mktypes="GOARCH=$GOARCH go tool cgo -godefs" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;; ;;
openbsd_386) openbsd_386)
mkasm="go run mkasm.go"
mkerrors="$mkerrors -m32" mkerrors="$mkerrors -m32"
mksyscall="go run mksyscall.go -l32 -openbsd" mksyscall="go run mksyscall.go -l32 -openbsd -libc"
mksysctl="go run mksysctl_openbsd.go" 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" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;; ;;
openbsd_amd64) openbsd_amd64)
mkasm="go run mkasm.go"
mkerrors="$mkerrors -m64" mkerrors="$mkerrors -m64"
mksyscall="go run mksyscall.go -openbsd" mksyscall="go run mksyscall.go -openbsd -libc"
mksysctl="go run mksysctl_openbsd.go" 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" mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;; ;;
openbsd_arm) openbsd_arm)
mkasm="go run mkasm.go"
mkerrors="$mkerrors" 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" 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 # Let the type of C char be signed for making the bare syscall
# API consistent across platforms. # API consistent across platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;; ;;
openbsd_arm64) openbsd_arm64)
mkasm="go run mkasm.go"
mkerrors="$mkerrors -m64" mkerrors="$mkerrors -m64"
mksyscall="go run mksyscall.go -openbsd" mksyscall="go run mksyscall.go -openbsd -libc"
mksysctl="go run mksysctl_openbsd.go" 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 # Let the type of C char be signed for making the bare syscall
# API consistent across platforms. # API consistent across platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
;; ;;
openbsd_mips64) openbsd_mips64)
mkasm="go run mkasm.go"
mkerrors="$mkerrors -m64" 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_ppc64)
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_riscv64)
mkasm="go run mkasm.go"
mkerrors="$mkerrors -m64"
mksyscall="go run mksyscall.go -openbsd -libc"
mksysctl="go run mksysctl_openbsd.go" 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 # Let the type of C char be signed for making the bare syscall
# API consistent across platforms. # API consistent across platforms.
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
@ -209,11 +232,6 @@ esac
if [ "$GOOSARCH" == "aix_ppc64" ]; then if [ "$GOOSARCH" == "aix_ppc64" ]; then
# aix/ppc64 script generates files instead of writing to stdin. # 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 " ; 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
# 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 elif [ "$GOOS" == "illumos" ]; then
# illumos code generation requires a --illumos switch # illumos code generation requires a --illumos switch
echo "$mksyscall -illumos -tags illumos,$GOARCH syscall_illumos.go |gofmt > zsyscall_illumos_$GOARCH.go"; echo "$mksyscall -illumos -tags illumos,$GOARCH syscall_illumos.go |gofmt > zsyscall_illumos_$GOARCH.go";
@ -227,5 +245,5 @@ esac
if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; 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 "$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 ) | $run

View File

@ -54,7 +54,7 @@ includes_AIX='
includes_Darwin=' includes_Darwin='
#define _DARWIN_C_SOURCE #define _DARWIN_C_SOURCE
#define KERNEL #define KERNEL 1
#define _DARWIN_USE_64_BIT_INODE #define _DARWIN_USE_64_BIT_INODE
#define __APPLE_USE_RFC_3542 #define __APPLE_USE_RFC_3542
#include <stdint.h> #include <stdint.h>
@ -75,6 +75,7 @@ includes_Darwin='
#include <sys/utsname.h> #include <sys/utsname.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/xattr.h> #include <sys/xattr.h>
#include <sys/vsock.h>
#include <net/bpf.h> #include <net/bpf.h>
#include <net/if.h> #include <net/if.h>
#include <net/if_types.h> #include <net/if_types.h>
@ -82,6 +83,9 @@ includes_Darwin='
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/ip.h> #include <netinet/ip.h>
#include <termios.h> #include <termios.h>
// for backwards compatibility because moved TIOCREMOTE to Kernel.framework after MacOSX12.0.sdk.
#define TIOCREMOTE 0x80047469
' '
includes_DragonFly=' includes_DragonFly='
@ -124,6 +128,7 @@ includes_FreeBSD='
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/ptrace.h>
#include <net/bpf.h> #include <net/bpf.h>
#include <net/if.h> #include <net/if.h>
#include <net/if_types.h> #include <net/if_types.h>
@ -198,9 +203,11 @@ struct ltchars {
#include <sys/timerfd.h> #include <sys/timerfd.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <sys/xattr.h> #include <sys/xattr.h>
#include <linux/audit.h>
#include <linux/bpf.h> #include <linux/bpf.h>
#include <linux/can.h> #include <linux/can.h>
#include <linux/can/error.h> #include <linux/can/error.h>
#include <linux/can/netlink.h>
#include <linux/can/raw.h> #include <linux/can/raw.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/cryptouser.h> #include <linux/cryptouser.h>
@ -210,6 +217,7 @@ struct ltchars {
#include <linux/ethtool_netlink.h> #include <linux/ethtool_netlink.h>
#include <linux/falloc.h> #include <linux/falloc.h>
#include <linux/fanotify.h> #include <linux/fanotify.h>
#include <linux/fib_rules.h>
#include <linux/filter.h> #include <linux/filter.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/fscrypt.h> #include <linux/fscrypt.h>
@ -217,8 +225,6 @@ struct ltchars {
#include <linux/genetlink.h> #include <linux/genetlink.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <linux/hidraw.h> #include <linux/hidraw.h>
#include <linux/icmp.h>
#include <linux/icmpv6.h>
#include <linux/if.h> #include <linux/if.h>
#include <linux/if_addr.h> #include <linux/if_addr.h>
#include <linux/if_alg.h> #include <linux/if_alg.h>
@ -229,13 +235,16 @@ struct ltchars {
#include <linux/if_packet.h> #include <linux/if_packet.h>
#include <linux/if_xdp.h> #include <linux/if_xdp.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/kcm.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/keyctl.h> #include <linux/keyctl.h>
#include <linux/landlock.h>
#include <linux/loop.h> #include <linux/loop.h>
#include <linux/lwtunnel.h> #include <linux/lwtunnel.h>
#include <linux/magic.h> #include <linux/magic.h>
#include <linux/memfd.h> #include <linux/memfd.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mount.h>
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/net_namespace.h> #include <linux/net_namespace.h>
@ -257,6 +266,7 @@ struct ltchars {
#include <linux/vm_sockets.h> #include <linux/vm_sockets.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/wireguard.h>
#include <mtd/ubi-user.h> #include <mtd/ubi-user.h>
#include <mtd/mtd-user.h> #include <mtd/mtd-user.h>
@ -287,6 +297,10 @@ struct ltchars {
#define SOL_NETLINK 270 #define SOL_NETLINK 270
#endif #endif
#ifndef SOL_SMC
#define SOL_SMC 286
#endif
#ifdef SOL_BLUETOOTH #ifdef SOL_BLUETOOTH
// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h // SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
// but it is already in bluetooth_linux.go // but it is already in bluetooth_linux.go
@ -467,7 +481,6 @@ ccflags="$@"
$2 !~ /^EQUIV_/ && $2 !~ /^EQUIV_/ &&
$2 !~ /^EXPR_/ && $2 !~ /^EXPR_/ &&
$2 !~ /^EVIOC/ && $2 !~ /^EVIOC/ &&
$2 !~ /^EV_/ &&
$2 ~ /^E[A-Z0-9_]+$/ || $2 ~ /^E[A-Z0-9_]+$/ ||
$2 ~ /^B[0-9_]+$/ || $2 ~ /^B[0-9_]+$/ ||
$2 ~ /^(OLD|NEW)DEV$/ || $2 ~ /^(OLD|NEW)DEV$/ ||
@ -499,10 +512,12 @@ ccflags="$@"
$2 ~ /^O?XTABS$/ || $2 ~ /^O?XTABS$/ ||
$2 ~ /^TC[IO](ON|OFF)$/ || $2 ~ /^TC[IO](ON|OFF)$/ ||
$2 ~ /^IN_/ || $2 ~ /^IN_/ ||
$2 ~ /^KCM/ ||
$2 ~ /^LANDLOCK_/ ||
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ || $2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
$2 ~ /^LO_(KEY|NAME)_SIZE$/ || $2 ~ /^LO_(KEY|NAME)_SIZE$/ ||
$2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ || $2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ ||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL)_/ || $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT)_/ ||
$2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ || $2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ ||
$2 ~ /^NFC_.*_(MAX)?SIZE$/ || $2 ~ /^NFC_.*_(MAX)?SIZE$/ ||
$2 ~ /^RAW_PAYLOAD_/ || $2 ~ /^RAW_PAYLOAD_/ ||
@ -517,10 +532,10 @@ ccflags="$@"
$2 ~ /^HW_MACHINE$/ || $2 ~ /^HW_MACHINE$/ ||
$2 ~ /^SYSCTL_VERS/ || $2 ~ /^SYSCTL_VERS/ ||
$2 !~ "MNT_BITS" && $2 !~ "MNT_BITS" &&
$2 ~ /^(MS|MNT|UMOUNT)_/ || $2 ~ /^(MS|MNT|MOUNT|UMOUNT)_/ ||
$2 ~ /^NS_GET_/ || $2 ~ /^NS_GET_/ ||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|TFD)_/ || $2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|PIOD|TFD)_/ ||
$2 ~ /^KEXEC_/ || $2 ~ /^KEXEC_/ ||
$2 ~ /^LINUX_REBOOT_CMD_/ || $2 ~ /^LINUX_REBOOT_CMD_/ ||
$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
@ -544,6 +559,7 @@ ccflags="$@"
$2 ~ /^CLONE_[A-Z_]+/ || $2 ~ /^CLONE_[A-Z_]+/ ||
$2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+)$/ && $2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+)$/ &&
$2 ~ /^(BPF|DLT)_/ || $2 ~ /^(BPF|DLT)_/ ||
$2 ~ /^AUDIT_/ ||
$2 ~ /^(CLOCK|TIMER)_/ || $2 ~ /^(CLOCK|TIMER)_/ ||
$2 ~ /^CAN_/ || $2 ~ /^CAN_/ ||
$2 ~ /^CAP_/ || $2 ~ /^CAP_/ ||
@ -563,9 +579,9 @@ ccflags="$@"
$2 ~ /^KEYCTL_/ || $2 ~ /^KEYCTL_/ ||
$2 ~ /^PERF_/ || $2 ~ /^PERF_/ ||
$2 ~ /^SECCOMP_MODE_/ || $2 ~ /^SECCOMP_MODE_/ ||
$2 ~ /^SEEK_/ ||
$2 ~ /^SPLICE_/ || $2 ~ /^SPLICE_/ ||
$2 ~ /^SYNC_FILE_RANGE_/ || $2 ~ /^SYNC_FILE_RANGE_/ ||
$2 !~ /^AUDIT_RECORD_MAGIC/ &&
$2 !~ /IOC_MAGIC/ && $2 !~ /IOC_MAGIC/ &&
$2 ~ /^[A-Z][A-Z0-9_]+_MAGIC2?$/ || $2 ~ /^[A-Z][A-Z0-9_]+_MAGIC2?$/ ||
$2 ~ /^(VM|VMADDR)_/ || $2 ~ /^(VM|VMADDR)_/ ||
@ -591,8 +607,10 @@ ccflags="$@"
$2 ~ /^DEVLINK_/ || $2 ~ /^DEVLINK_/ ||
$2 ~ /^ETHTOOL_/ || $2 ~ /^ETHTOOL_/ ||
$2 ~ /^LWTUNNEL_IP/ || $2 ~ /^LWTUNNEL_IP/ ||
$2 ~ /^ITIMER_/ ||
$2 !~ "WMESGLEN" && $2 !~ "WMESGLEN" &&
$2 ~ /^W[A-Z0-9]+$/ || $2 ~ /^W[A-Z0-9]+$/ ||
$2 ~ /^P_/ ||
$2 ~/^PPPIOC/ || $2 ~/^PPPIOC/ ||
$2 ~ /^FAN_|FANOTIFY_/ || $2 ~ /^FAN_|FANOTIFY_/ ||
$2 == "HID_MAX_DESCRIPTOR_SIZE" || $2 == "HID_MAX_DESCRIPTOR_SIZE" ||
@ -601,6 +619,8 @@ ccflags="$@"
$2 ~ /^MTD/ || $2 ~ /^MTD/ ||
$2 ~ /^OTP/ || $2 ~ /^OTP/ ||
$2 ~ /^MEM/ || $2 ~ /^MEM/ ||
$2 ~ /^WG/ ||
$2 ~ /^FIB_RULE_/ ||
$2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)} $2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)}
$2 ~ /^__WCOREFLAG$/ {next} $2 ~ /^__WCOREFLAG$/ {next}
$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)} $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
@ -622,7 +642,7 @@ errors=$(
signals=$( signals=$(
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags | echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' | awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' | grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' |
sort sort
) )
@ -632,7 +652,7 @@ echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
sort >_error.grep sort >_error.grep
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags | echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' | awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' | grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' |
sort >_signal.grep sort >_signal.grep
echo '// mkerrors.sh' "$@" echo '// mkerrors.sh' "$@"

View File

@ -34,3 +34,52 @@ func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) {
ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0])) ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0]))
return &ucred, nil 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
}
}

View File

@ -52,6 +52,20 @@ func ParseSocketControlMessage(b []byte) ([]SocketControlMessage, error) {
return msgs, nil 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) { func socketControlMessageHeaderAndData(b []byte) (*Cmsghdr, []byte, error) {
h := (*Cmsghdr)(unsafe.Pointer(&b[0])) h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
if h.Len < SizeofCmsghdr || uint64(h.Len) > uint64(len(b)) { if h.Len < SizeofCmsghdr || uint64(h.Len) > uint64(len(b)) {

27
vendor/golang.org/x/sys/unix/str.go generated vendored
View File

@ -1,27 +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.
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +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:])
}

View File

@ -29,8 +29,6 @@ import (
"bytes" "bytes"
"strings" "strings"
"unsafe" "unsafe"
"golang.org/x/sys/internal/unsafeheader"
) )
// ByteSliceFromString returns a NUL-terminated slice of bytes // ByteSliceFromString returns a NUL-terminated slice of bytes
@ -82,13 +80,7 @@ func BytePtrToString(p *byte) string {
ptr = unsafe.Pointer(uintptr(ptr) + 1) ptr = unsafe.Pointer(uintptr(ptr) + 1)
} }
var s []byte return string(unsafe.Slice(p, n))
h := (*unsafeheader.Slice)(unsafe.Pointer(&s))
h.Data = unsafe.Pointer(p)
h.Len = n
h.Cap = n
return string(s)
} }
// Single-word zero for use when we need a valid pointer to 0 bytes. // Single-word zero for use when we need a valid pointer to 0 bytes.

View File

@ -37,6 +37,7 @@ func Creat(path string, mode uint32) (fd int, err error) {
} }
//sys utimes(path string, times *[2]Timeval) (err error) //sys utimes(path string, times *[2]Timeval) (err error)
func Utimes(path string, tv []Timeval) error { func Utimes(path string, tv []Timeval) error {
if len(tv) != 2 { if len(tv) != 2 {
return EINVAL return EINVAL
@ -45,6 +46,7 @@ func Utimes(path string, tv []Timeval) error {
} }
//sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error) //sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error)
func UtimesNano(path string, ts []Timespec) error { func UtimesNano(path string, ts []Timespec) error {
if len(ts) != 2 { if len(ts) != 2 {
return EINVAL return EINVAL
@ -70,9 +72,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8) p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port) p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ { sa.raw.Addr = sa.Addr
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
} }
@ -85,9 +85,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
p[0] = byte(sa.Port >> 8) p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port) p[1] = byte(sa.Port)
sa.raw.Scope_id = sa.ZoneId sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ { sa.raw.Addr = sa.Addr
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
} }
@ -219,20 +217,63 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) {
return return
} }
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) {
// Recvmsg not implemented on AIX var msg Msghdr
sa := new(SockaddrUnix) msg.Name = (*byte)(unsafe.Pointer(rsa))
return -1, -1, -1, sa, ENOSYS msg.Namelen = uint32(SizeofSockaddrAny)
} var dummy byte
if len(oob) > 0 {
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { // receive at least one normal byte
_, err = SendmsgN(fd, p, oob, to, flags) 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 return
} }
func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
// SendmsgN not implemented on AIX var msg Msghdr
return -1, ENOSYS 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) { func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
@ -261,9 +302,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa := new(SockaddrInet4) sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port)) p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]) sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ { sa.Addr = pp.Addr
sa.Addr[i] = pp.Addr[i]
}
return sa, nil return sa, nil
case AF_INET6: case AF_INET6:
@ -272,9 +311,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
p := (*[2]byte)(unsafe.Pointer(&pp.Port)) p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]) sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ { sa.Addr = pp.Addr
sa.Addr[i] = pp.Addr[i]
}
return sa, nil return sa, nil
} }
return nil, EAFNOSUPPORT return nil, EAFNOSUPPORT
@ -314,11 +351,13 @@ func direntNamlen(buf []byte) (uint64, bool) {
} }
//sys getdirent(fd int, buf []byte) (n int, err error) //sys getdirent(fd int, buf []byte) (n int, err error)
func Getdents(fd int, buf []byte) (n int, err error) { func Getdents(fd int, buf []byte) (n int, err error) {
return getdirent(fd, buf) return getdirent(fd, buf)
} }
//sys wait4(pid Pid_t, status *_C_int, options int, rusage *Rusage) (wpid Pid_t, err error) //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) { func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
var status _C_int var status _C_int
var r Pid_t var r Pid_t
@ -385,6 +424,12 @@ func (w WaitStatus) TrapCause() int { return -1 }
//sys fcntl(fd int, cmd int, arg int) (val int, err error) //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 * Direct access
*/ */
@ -401,7 +446,6 @@ func (w WaitStatus) TrapCause() int { return -1 }
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) //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 Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
//sys Fdatasync(fd int) (err error) //sys Fdatasync(fd int) (err error)
//sys Fsync(fd int) (err error)
// readdir_r // readdir_r
//sysnb Getpgid(pid int) (pgid int, err error) //sysnb Getpgid(pid int) (pgid int, err error)
@ -462,8 +506,8 @@ func (w WaitStatus) TrapCause() int { return -1 }
//sys Listen(s int, n int) (err error) //sys Listen(s int, n int) (err error)
//sys lstat(path string, stat *Stat_t) (err error) //sys lstat(path string, stat *Stat_t) (err error)
//sys Pause() (err error) //sys Pause() (err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = pread64 //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 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 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) //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) //sysnb Setregid(rgid int, egid int) (err error)
@ -523,8 +567,10 @@ func Pipe(p []int) (err error) {
} }
var pp [2]_C_int var pp [2]_C_int
err = pipe(&pp) err = pipe(&pp)
p[0] = int(pp[0]) if err == nil {
p[1] = int(pp[1]) p[0] = int(pp[0])
p[1] = int(pp[1])
}
return return
} }
@ -544,6 +590,7 @@ func Poll(fds []PollFd, timeout int) (n int, err error) {
//sys Getsystemcfg(label int) (n uint64) //sys Getsystemcfg(label int) (n uint64)
//sys umount(target string) (err error) //sys umount(target string) (err error)
func Unmount(target string, flags int) (err error) { func Unmount(target string, flags int) (err error) {
if flags != 0 { if flags != 0 {
// AIX doesn't have any flags for umount. // AIX doesn't have any flags for umount.

View File

@ -163,9 +163,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port >> 8) p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port) p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ { sa.raw.Addr = sa.Addr
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
} }
@ -179,9 +177,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
p[0] = byte(sa.Port >> 8) p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port) p[1] = byte(sa.Port)
sa.raw.Scope_id = sa.ZoneId sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ { sa.raw.Addr = sa.Addr
sa.raw.Addr[i] = sa.Addr[i]
}
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
} }
@ -210,9 +206,7 @@ func (sa *SockaddrDatalink) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Nlen = sa.Nlen sa.raw.Nlen = sa.Nlen
sa.raw.Alen = sa.Alen sa.raw.Alen = sa.Alen
sa.raw.Slen = sa.Slen sa.raw.Slen = sa.Slen
for i := 0; i < len(sa.raw.Data); i++ { sa.raw.Data = sa.Data
sa.raw.Data[i] = sa.Data[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrDatalink, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrDatalink, nil
} }
@ -228,9 +222,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa.Nlen = pp.Nlen sa.Nlen = pp.Nlen
sa.Alen = pp.Alen sa.Alen = pp.Alen
sa.Slen = pp.Slen sa.Slen = pp.Slen
for i := 0; i < len(sa.Data); i++ { sa.Data = pp.Data
sa.Data[i] = pp.Data[i]
}
return sa, nil return sa, nil
case AF_UNIX: case AF_UNIX:
@ -262,9 +254,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa := new(SockaddrInet4) sa := new(SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port)) p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]) sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ { sa.Addr = pp.Addr
sa.Addr[i] = pp.Addr[i]
}
return sa, nil return sa, nil
case AF_INET6: case AF_INET6:
@ -273,9 +263,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
p := (*[2]byte)(unsafe.Pointer(&pp.Port)) p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1]) sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ { sa.Addr = pp.Addr
sa.Addr[i] = pp.Addr[i]
}
return sa, nil return sa, nil
} }
return anyToSockaddrGOOS(fd, rsa) return anyToSockaddrGOOS(fd, rsa)
@ -337,80 +325,62 @@ func GetsockoptString(fd, level, opt int) (string, error) {
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (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 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 msg Msghdr
var rsa RawSockaddrAny msg.Name = (*byte)(unsafe.Pointer(rsa))
msg.Name = (*byte)(unsafe.Pointer(&rsa))
msg.Namelen = uint32(SizeofSockaddrAny) 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 var dummy byte
if len(oob) > 0 { if len(oob) > 0 {
// receive at least one normal byte // receive at least one normal byte
if len(p) == 0 { if emptyIovecs(iov) {
iov.Base = &dummy var iova [1]Iovec
iov.SetLen(1) iova[0].Base = &dummy
iova[0].SetLen(1)
iov = iova[:]
} }
msg.Control = (*byte)(unsafe.Pointer(&oob[0])) msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
msg.SetControllen(len(oob)) msg.SetControllen(len(oob))
} }
msg.Iov = &iov if len(iov) > 0 {
msg.Iovlen = 1 msg.Iov = &iov[0]
msg.SetIovlen(len(iov))
}
if n, err = recvmsg(fd, &msg, flags); err != nil { if n, err = recvmsg(fd, &msg, flags); err != nil {
return return
} }
oobn = int(msg.Controllen) oobn = int(msg.Controllen)
recvflags = int(msg.Flags) 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 return
} }
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) //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) { func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n 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
}
}
var msg Msghdr var msg Msghdr
msg.Name = (*byte)(unsafe.Pointer(ptr)) msg.Name = (*byte)(unsafe.Pointer(ptr))
msg.Namelen = uint32(salen) 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 dummy byte
var empty bool
if len(oob) > 0 { if len(oob) > 0 {
// send at least one normal byte // send at least one normal byte
if len(p) == 0 { empty = emptyIovecs(iov)
iov.Base = &dummy if empty {
iov.SetLen(1) var iova [1]Iovec
iova[0].Base = &dummy
iova[0].SetLen(1)
iov = iova[:]
} }
msg.Control = (*byte)(unsafe.Pointer(&oob[0])) msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
msg.SetControllen(len(oob)) msg.SetControllen(len(oob))
} }
msg.Iov = &iov if len(iov) > 0 {
msg.Iovlen = 1 msg.Iov = &iov[0]
msg.SetIovlen(len(iov))
}
if n, err = sendmsg(fd, &msg, flags); err != nil { if n, err = sendmsg(fd, &msg, flags); err != nil {
return 0, err return 0, err
} }
if len(oob) > 0 && len(p) == 0 { if len(oob) > 0 && empty {
n = 0 n = 0
} }
return n, nil return n, nil
@ -583,12 +553,7 @@ func UtimesNano(path string, ts []Timespec) error {
if len(ts) != 2 { if len(ts) != 2 {
return EINVAL return EINVAL
} }
// Darwin setattrlist can set nanosecond timestamps err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
err := setattrlistTimes(path, ts, 0)
if err != ENOSYS {
return err
}
err = utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
if err != ENOSYS { if err != ENOSYS {
return err return err
} }
@ -608,10 +573,6 @@ func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error {
if len(ts) != 2 { if len(ts) != 2 {
return EINVAL return EINVAL
} }
err := setattrlistTimes(path, ts, flags)
if err != ENOSYS {
return err
}
return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags) return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
} }

View File

@ -1,32 +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.
//go:build darwin && go1.12 && !go1.13
// +build darwin,go1.12,!go1.13
package unix
import (
"unsafe"
)
const _SYS_GETDIRENTRIES64 = 344
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
}

View File

@ -1,108 +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.
//go:build darwin && go1.13
// +build darwin,go1.13
package unix
import (
"unsafe"
"golang.org/x/sys/internal/unsafeheader"
)
//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.
var s []byte
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&s))
hdr.Data = unsafe.Pointer(&entry)
hdr.Cap = reclen
hdr.Len = 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
}

View File

@ -13,11 +13,102 @@
package unix package unix
import ( import (
"fmt"
"runtime" "runtime"
"syscall" "syscall"
"unsafe" "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(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
}
return n, nil
}
// SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets. // SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets.
type SockaddrDatalink struct { type SockaddrDatalink struct {
Len uint8 Len uint8
@ -47,6 +138,30 @@ func (sa *SockaddrCtl) sockaddr() (unsafe.Pointer, _Socklen, error) {
return unsafe.Pointer(&sa.raw), SizeofSockaddrCtl, nil 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) { func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
switch rsa.Addr.Family { switch rsa.Addr.Family {
case AF_SYSTEM: case AF_SYSTEM:
@ -57,6 +172,13 @@ func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
sa.Unit = pp.Sc_unit sa.Unit = pp.Sc_unit
return sa, nil 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 return nil, EAFNOSUPPORT
} }
@ -109,16 +231,6 @@ func direntNamlen(buf []byte) (uint64, bool) {
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) } 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 PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
type attrList struct {
bitmapCount uint16
_ uint16
CommonAttr uint32
VolAttr uint32
DirAttr uint32
FileAttr uint32
Forkattr uint32
}
//sysnb pipe(p *[2]int32) (err error) //sysnb pipe(p *[2]int32) (err error)
func Pipe(p []int) (err error) { func Pipe(p []int) (err error) {
@ -127,8 +239,10 @@ func Pipe(p []int) (err error) {
} }
var x [2]int32 var x [2]int32
err = pipe(&x) err = pipe(&x)
p[0] = int(x[0]) if err == nil {
p[1] = int(x[1]) p[0] = int(x[0])
p[1] = int(x[1])
}
return return
} }
@ -248,36 +362,7 @@ func Flistxattr(fd int, dest []byte) (sz int, err error) {
return flistxattr(fd, xattrPointer(dest), len(dest), 0) return flistxattr(fd, xattrPointer(dest), len(dest), 0)
} }
func setattrlistTimes(path string, times []Timespec, flags int) error { //sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err 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
}
/* /*
* Wrapped * Wrapped
@ -398,8 +483,69 @@ func GetsockoptXucred(fd, level, opt int) (*Xucred, error) {
return x, err 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
}
// 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 {
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 sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (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 * Exposed directly
*/ */
@ -455,11 +601,12 @@ func GetsockoptXucred(fd, level, opt int) (*Xucred, error) {
//sys Mkdirat(dirfd int, 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 Mkfifo(path string, mode uint32) (err error)
//sys Mknod(path string, mode uint32, dev int) (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 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 Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error)
//sys Pathconf(path string, name int) (val 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 pread(fd int, p []byte, offset int64) (n int, err error)
//sys Pwrite(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 read(fd int, p []byte) (n int, err error)
//sys Readlink(path string, buf []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) //sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error)
@ -523,7 +670,6 @@ func GetsockoptXucred(fd, level, opt int) (*Xucred, error) {
// Nfssvc // Nfssvc
// Getfh // Getfh
// Quotactl // Quotactl
// Mount
// Csops // Csops
// Waitid // Waitid
// Add_profil // Add_profil
@ -557,10 +703,6 @@ func GetsockoptXucred(fd, level, opt int) (*Xucred, error) {
// Msgget // Msgget
// Msgsnd // Msgsnd
// Msgrcv // Msgrcv
// Shmat
// Shmctl
// Shmdt
// Shmget
// Shm_open // Shm_open
// Shm_unlink // Shm_unlink
// Sem_open // Sem_open

View File

@ -101,7 +101,10 @@ func Pipe(p []int) (err error) {
if len(p) != 2 { if len(p) != 2 {
return EINVAL return EINVAL
} }
p[0], p[1], err = pipe() r, w, err := pipe()
if err == nil {
p[0], p[1] = r, w
}
return return
} }
@ -114,17 +117,22 @@ func Pipe2(p []int, flags int) (err error) {
var pp [2]_C_int var pp [2]_C_int
// pipe2 on dragonfly takes an fds array as an argument, but still // pipe2 on dragonfly takes an fds array as an argument, but still
// returns the file descriptors. // returns the file descriptors.
p[0], p[1], err = pipe2(&pp, flags) r, w, err := pipe2(&pp, flags)
if err == nil {
p[0], p[1] = r, w
}
return err return err
} }
//sys extpread(fd int, p []byte, flags int, offset int64) (n int, err error) //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) return extpread(fd, p, 0, offset)
} }
//sys extpwrite(fd int, p []byte, flags int, offset int64) (n int, err error) //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) return extpwrite(fd, p, 0, offset)
} }
@ -163,11 +171,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
return 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 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
@ -252,6 +255,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Chmod(path string, mode uint32) (err error) //sys Chmod(path string, mode uint32) (err error)
//sys Chown(path string, uid int, gid int) (err error) //sys Chown(path string, uid int, gid int) (err error)
//sys Chroot(path string) (err error) //sys Chroot(path string) (err error)
//sys ClockGettime(clockid int32, time *Timespec) (err error)
//sys Close(fd int) (err error) //sys Close(fd int) (err error)
//sys Dup(fd int) (nfd int, err error) //sys Dup(fd int) (nfd int, err error)
//sys Dup2(from int, to int) (err error) //sys Dup2(from int, to int) (err error)

View File

@ -17,25 +17,12 @@ import (
"unsafe" "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. // See https://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/versions.html.
var ( var (
osreldateOnce sync.Once osreldateOnce sync.Once
osreldate uint32 osreldate uint32
) )
// INO64_FIRST from /usr/src/lib/libc/sys/compat-ino64.h
const _ino64First = 1200031
func supportsABI(ver uint32) bool { func supportsABI(ver uint32) bool {
osreldateOnce.Do(func() { osreldate, _ = SysctlUint32("kern.osreldate") }) osreldateOnce.Do(func() { osreldate, _ = SysctlUint32("kern.osreldate") })
return osreldate >= ver return osreldate >= ver
@ -110,8 +97,10 @@ func Pipe2(p []int, flags int) error {
} }
var pp [2]_C_int var pp [2]_C_int
err := pipe2(&pp, flags) err := pipe2(&pp, flags)
p[0] = int(pp[0]) if err == nil {
p[1] = int(pp[1]) p[0] = int(pp[0])
p[1] = int(pp[1])
}
return err return err
} }
@ -157,46 +146,21 @@ func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) {
func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
var ( var (
_p0 unsafe.Pointer _p0 unsafe.Pointer
bufsize uintptr bufsize uintptr
oldBuf []statfs_freebsd11_t
needsConvert bool
) )
if len(buf) > 0 { if len(buf) > 0 {
if supportsABI(_ino64First) { _p0 = unsafe.Pointer(&buf[0])
_p0 = unsafe.Pointer(&buf[0]) bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
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
}
} }
var sysno uintptr = SYS_GETFSSTAT r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
if supportsABI(_ino64First) {
sysno = SYS_GETFSSTAT_FREEBSD12
}
r0, _, e1 := Syscall(sysno, uintptr(_p0), bufsize, uintptr(flags))
n = int(r0) n = int(r0)
if e1 != 0 { if e1 != 0 {
err = e1 err = e1
} }
if e1 == 0 && needsConvert {
for i := range oldBuf {
buf[i].convertFrom(&oldBuf[i])
}
}
return 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 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
@ -248,87 +212,11 @@ func Uname(uname *Utsname) error {
} }
func Stat(path string, st *Stat_t) (err error) { func Stat(path string, st *Stat_t) (err error) {
var oldStat stat_freebsd11_t return Fstatat(AT_FDCWD, path, st, 0)
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
} }
func Lstat(path string, st *Stat_t) (err error) { func Lstat(path string, st *Stat_t) (err error) {
var oldStat stat_freebsd11_t return Fstatat(AT_FDCWD, path, st, AT_SYMLINK_NOFOLLOW)
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
} }
func Getdents(fd int, buf []byte) (n int, err error) { func Getdents(fd int, buf []byte) (n int, err error) {
@ -336,162 +224,25 @@ func Getdents(fd int, buf []byte) (n int, err error) {
} }
func Getdirentries(fd int, buf []byte, basep *uintptr) (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 {
if basep == nil || unsafe.Sizeof(*basep) == 8 { return getdirentries(fd, buf, (*uint64)(unsafe.Pointer(basep)))
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 syscall needs a 64-bit base. On 32-bit machines
// The old syscall entries are smaller than the new. Use 1/4 of the original // we can't just use the basep passed in. See #32498.
// buffer size rounded up to DIRBLKSIZ (see /usr/src/lib/libc/sys/getdirentries.c). var base uint64 = uint64(*basep)
oldBufLen := roundup(len(buf)/4, _dirblksiz) n, err = getdirentries(fd, buf, &base)
oldBuf := make([]byte, oldBufLen) *basep = uintptr(base)
n, err = getdirentries(fd, oldBuf, basep) if base>>32 != 0 {
if err == nil && n > 0 { // We can't stuff the base back into a uintptr, so any
n = convertFromDirents11(buf, oldBuf[:n]) // future calls would be suspect. Generate an error.
// EIO is allowed by getdirentries.
err = EIO
} }
return return
} }
func Mknod(path string, mode uint32, dev uint64) (err error) { func Mknod(path string, mode uint32, dev uint64) (err error) {
var oldDev int return Mknodat(AT_FDCWD, path, mode, dev)
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
} }
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
@ -504,31 +255,31 @@ 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 ptrace(request int, pid int, addr uintptr, data int) (err error)
func PtraceAttach(pid int) (err error) { 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) { 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) { 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) { func PtraceGetFpRegs(pid int, fpregsout *FpReg) (err error) {
return ptrace(PTRACE_GETFPREGS, pid, uintptr(unsafe.Pointer(fpregsout)), 0) return ptrace(PT_GETFPREGS, pid, uintptr(unsafe.Pointer(fpregsout)), 0)
} }
func PtraceGetRegs(pid int, regsout *Reg) (err error) { func PtraceGetRegs(pid int, regsout *Reg) (err error) {
return ptrace(PTRACE_GETREGS, pid, uintptr(unsafe.Pointer(regsout)), 0) return ptrace(PT_GETREGS, pid, uintptr(unsafe.Pointer(regsout)), 0)
} }
func PtraceLwpEvents(pid int, enable int) (err error) { 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) { func PtraceLwpInfo(pid int, info uintptr) (err error) {
return ptrace(PTRACE_LWPINFO, pid, info, int(unsafe.Sizeof(PtraceLwpInfoStruct{}))) return ptrace(PT_LWPINFO, pid, info, int(unsafe.Sizeof(PtraceLwpInfoStruct{})))
} }
func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) { func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) {
@ -548,11 +299,11 @@ func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) {
} }
func PtraceSetRegs(pid int, regs *Reg) (err error) { func PtraceSetRegs(pid int, regs *Reg) (err error) {
return ptrace(PTRACE_SETREGS, pid, uintptr(unsafe.Pointer(regs)), 0) return ptrace(PT_SETREGS, pid, uintptr(unsafe.Pointer(regs)), 0)
} }
func PtraceSingleStep(pid int) (err error) { func PtraceSingleStep(pid int) (err error) {
return ptrace(PTRACE_SINGLESTEP, pid, 1, 0) return ptrace(PT_STEP, pid, 1, 0)
} }
/* /*
@ -568,6 +319,7 @@ func PtraceSingleStep(pid int) (err error) {
//sys Chmod(path string, mode uint32) (err error) //sys Chmod(path string, mode uint32) (err error)
//sys Chown(path string, uid int, gid int) (err error) //sys Chown(path string, uid int, gid int) (err error)
//sys Chroot(path string) (err error) //sys Chroot(path string) (err error)
//sys ClockGettime(clockid int32, time *Timespec) (err error)
//sys Close(fd int) (err error) //sys Close(fd int) (err error)
//sys Dup(fd int) (nfd int, err error) //sys Dup(fd int) (nfd int, err error)
//sys Dup2(from int, to int) (err error) //sys Dup2(from int, to int) (err error)
@ -594,16 +346,12 @@ func PtraceSingleStep(pid int) (err error) {
//sys Fchownat(dirfd int, path string, uid int, gid int, flags 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 Flock(fd int, how int) (err error)
//sys Fpathconf(fd int, name int) (val 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(fd int, stat *Stat_t) (err error)
//sys fstat_freebsd12(fd int, stat *Stat_t) (err error) //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
//sys fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error) //sys Fstatfs(fd int, stat *Statfs_t) (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 Fsync(fd int) (err error) //sys Fsync(fd int) (err error)
//sys Ftruncate(fd int, length int64) (err error) //sys Ftruncate(fd int, length int64) (err error)
//sys getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) //sys getdirentries(fd int, buf []byte, basep *uint64) (n int, err error)
//sys getdirentries_freebsd12(fd int, buf []byte, basep *uint64) (n int, err error)
//sys Getdtablesize() (size int) //sys Getdtablesize() (size int)
//sysnb Getegid() (egid int) //sysnb Getegid() (egid int)
//sysnb Geteuid() (uid int) //sysnb Geteuid() (uid int)
@ -625,19 +373,16 @@ func PtraceSingleStep(pid int) (err error) {
//sys Link(path string, link string) (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 Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error)
//sys Listen(s int, backlog 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 Mkdir(path string, mode uint32) (err error)
//sys Mkdirat(dirfd int, 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 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 uint64) (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 Nanosleep(time *Timespec, leftover *Timespec) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
//sys Open(path string, mode int, perm uint32) (fd int, 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 Openat(fdat int, path string, mode int, perm uint32) (fd int, err error)
//sys Pathconf(path string, name int) (val 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 pread(fd int, p []byte, offset int64) (n int, err error)
//sys Pwrite(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 read(fd int, p []byte) (n int, err error)
//sys Readlink(path string, buf []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) //sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error)
@ -661,9 +406,7 @@ func PtraceSingleStep(pid int) (err error) {
//sysnb Setsid() (pid int, err error) //sysnb Setsid() (pid int, err error)
//sysnb Settimeofday(tp *Timeval) (err error) //sysnb Settimeofday(tp *Timeval) (err error)
//sysnb Setuid(uid int) (err error) //sysnb Setuid(uid int) (err error)
//sys stat(path string, stat *stat_freebsd11_t) (err error) //sys Statfs(path string, stat *Statfs_t) (err error)
//sys statfs(path string, stat *statfs_freebsd11_t) (err error)
//sys statfs_freebsd12(path string, stat *Statfs_t) (err error)
//sys Symlink(path string, link string) (err error) //sys Symlink(path string, link string) (err error)
//sys Symlinkat(oldpath string, newdirfd int, newpath string) (err error) //sys Symlinkat(oldpath string, newdirfd int, newpath string) (err error)
//sys Sync() (err error) //sys Sync() (err error)

View File

@ -57,11 +57,11 @@ 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 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) { func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
return ptrace(PTRACE_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0) return ptrace(PT_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
} }
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) { 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)} ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint32(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0) err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err return int(ioDesc.Len), err
} }

View File

@ -57,11 +57,11 @@ 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 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) { func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
return ptrace(PTRACE_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0) return ptrace(PT_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
} }
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) { 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)} ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint64(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0) err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err return int(ioDesc.Len), err
} }

View File

@ -57,7 +57,7 @@ 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 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) { 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)} ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint32(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0) err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err return int(ioDesc.Len), err
} }

View File

@ -57,7 +57,7 @@ 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 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) { 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)} ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint64(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0) err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err return int(ioDesc.Len), err
} }

Some files were not shown because too many files have changed in this diff Show More