Refactor layout to go-style, update deps
This commit is contained in:
14
Makefile
14
Makefile
@@ -1,10 +1,8 @@
|
|||||||
#!/usr/bin/env gmake -f
|
#!/usr/bin/env gmake -f
|
||||||
|
|
||||||
BUILDOPTS=-ldflags="-s -w" -a -gcflags=all=-l -trimpath
|
BUILDOPTS=-ldflags="-s -w" -a -gcflags=all=-l -trimpath
|
||||||
FILELIST= bf.go buny.go commands.go collection.go event_parser.go globals.go lib.go main.go norm_string.go \
|
MYNAME=buny-jabber-bot
|
||||||
read_config.go types.go
|
BINARY=$(MYNAME)
|
||||||
|
|
||||||
BINARY=buny-jabber-bot
|
|
||||||
|
|
||||||
# На windows имя бинарника может зависеть не только от платформы, но и от выбранной цели, для linux-а суффикс .exe
|
# На windows имя бинарника может зависеть не только от платформы, но и от выбранной цели, для linux-а суффикс .exe
|
||||||
# не нужен
|
# не нужен
|
||||||
@@ -34,21 +32,21 @@ ifeq ($(OS),Windows_NT)
|
|||||||
# вариант с powershell на windows
|
# вариант с powershell на windows
|
||||||
ifeq ($(SHELL),sh.exe)
|
ifeq ($(SHELL),sh.exe)
|
||||||
SET CGO_ENABLED=0
|
SET CGO_ENABLED=0
|
||||||
go build ${BUILDOPTS} -o ${BINARY} ${FILELIST}
|
go build ${BUILDOPTS} -o ${BINARY} ./cmd/${MYNAME}
|
||||||
else
|
else
|
||||||
# вариант с jetbrains golang на windows
|
# вариант с jetbrains golang на windows
|
||||||
CGO_ENABLED=0
|
CGO_ENABLED=0
|
||||||
go build ${BUILDOPTS} -o ${BINARY} ${FILELIST}
|
go build ${BUILDOPTS} -o ${BINARY} ./cmd/${MYNAME}
|
||||||
endif
|
endif
|
||||||
# вариант с bash/git (windows) и bash (linux)
|
# вариант с bash/git (windows) и bash (linux)
|
||||||
else
|
else
|
||||||
CGO_ENABLED=0 go build ${BUILDOPTS} -o ${BINARY} ${FILELIST}
|
CGO_ENABLED=0 go build ${BUILDOPTS} -o ${BINARY} ./cmd/${MYNAME}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
## Удаляем бинарник средствами go
|
## Удаляем бинарник средствами go
|
||||||
clean:
|
clean:
|
||||||
go clean
|
$(RM) ${BINARY}
|
||||||
|
|
||||||
|
|
||||||
## Служебный таргет, для целей разработки. Обновляет завендоренные либы, брутальным образом.
|
## Служебный таргет, для целей разработки. Обновляет завендоренные либы, брутальным образом.
|
||||||
|
|||||||
90
globals.go
90
globals.go
@@ -1,90 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/eleksir/go-xmpp"
|
|
||||||
"github.com/jbrukh/bayesian"
|
|
||||||
"gopkg.in/tomb.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
Bad bayesian.Class = "Bad"
|
|
||||||
Good bayesian.Class = "Good"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Config - это у нас глобальная штука :) .
|
|
||||||
var config myConfig
|
|
||||||
|
|
||||||
// Списки тех, кого мы не баним никогда.
|
|
||||||
var whiteList myWhiteList
|
|
||||||
|
|
||||||
// Списки злодеев, которых мы баним.
|
|
||||||
var blackList myBlackList
|
|
||||||
|
|
||||||
// Ставится в true, если мы получили сигнал на выключение.
|
|
||||||
var shutdown = false
|
|
||||||
|
|
||||||
// Чтобы не организовывать драку за установку коннекта.
|
|
||||||
var connecting = false
|
|
||||||
|
|
||||||
// Глобальное состояние соединения.
|
|
||||||
var isConnected = false
|
|
||||||
|
|
||||||
// Канал, в который приходят уведомления для хэндлера сигналов от траппера сигналов.
|
|
||||||
var sigChan = make(chan os.Signal, 1)
|
|
||||||
|
|
||||||
// Основной инстанс xmpp-клиента.
|
|
||||||
var talk *xmpp.Client
|
|
||||||
|
|
||||||
// Опции подключения к xmpp-серверу.
|
|
||||||
var options *xmpp.Options
|
|
||||||
|
|
||||||
// Список комнат, в которых находится бот.
|
|
||||||
var roomsConnected []string
|
|
||||||
|
|
||||||
// Время последней активности, нужно для jabber:iq:last.
|
|
||||||
var lastActivity int64
|
|
||||||
|
|
||||||
// Время последней активности, нужно для c2s пингов - посылаем пинги, только если давненько ничего не приходило с
|
|
||||||
// сервера.
|
|
||||||
var lastServerActivity int64
|
|
||||||
|
|
||||||
// Время последней активности MUC-ов, нужно для пингов - посылаем пинги, только если давненько ничего не приходило из
|
|
||||||
// muc-ов.
|
|
||||||
var lastMucActivity *Collection
|
|
||||||
|
|
||||||
// Получен ли ответ на запрос disco#info к серверу.
|
|
||||||
var serverCapsQueried bool
|
|
||||||
|
|
||||||
// sync.Map-ка с капабилити сервера.
|
|
||||||
var serverCapsList *Collection
|
|
||||||
|
|
||||||
// sync.Map-ка с комнатами и их capability.
|
|
||||||
var mucCapsList *Collection
|
|
||||||
|
|
||||||
// Время, когда был отправлен c2s ping.
|
|
||||||
var serverPingTimestampTx int64
|
|
||||||
|
|
||||||
// Время, когда был принят s2c pong.
|
|
||||||
var serverPingTimestampRx int64
|
|
||||||
|
|
||||||
// Объектик для хранения стейта утилизатора горутинок.
|
|
||||||
var gTomb tomb.Tomb
|
|
||||||
|
|
||||||
// sync.Map-ка со списком участников конференций (в json-формате, согласно структуре xmpp.Presence, "room".[]json).
|
|
||||||
var roomPresences *Collection
|
|
||||||
|
|
||||||
// Переменные для простенького нормализатора текста.
|
|
||||||
var (
|
|
||||||
// Знаки препинания раз.
|
|
||||||
pMarks = []string{".", ",", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "{", "}", "<", ">", "[", "]", "\\"}
|
|
||||||
|
|
||||||
// Знаки препинания два-с.
|
|
||||||
pMarks2 = []string{"-", "_", "+", "=", ":", ";", "'", "`", "~", "\""}
|
|
||||||
|
|
||||||
// Символы новой строки.
|
|
||||||
newLines = []string{"\n", "\r", "\n\r", "\r\n"}
|
|
||||||
)
|
|
||||||
|
|
||||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
|
||||||
10
go.mod
10
go.mod
@@ -1,6 +1,6 @@
|
|||||||
module buny-jabber-bot
|
module buny-jabber-bot
|
||||||
|
|
||||||
go 1.22
|
go 1.22.8
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
@@ -8,12 +8,12 @@ require (
|
|||||||
github.com/hjson/hjson-go v3.3.0+incompatible
|
github.com/hjson/hjson-go v3.3.0+incompatible
|
||||||
github.com/jbrukh/bayesian v0.0.0-20231117143245-13ae6f916c7a
|
github.com/jbrukh/bayesian v0.0.0-20231117143245-13ae6f916c7a
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
golang.org/x/crypto v0.25.0 // indirect
|
golang.org/x/crypto v0.10.0 // indirect
|
||||||
golang.org/x/sys v0.22.0 // indirect
|
golang.org/x/sys v0.9.0 // indirect
|
||||||
golang.org/x/text v0.16.0 // indirect
|
golang.org/x/text v0.10.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
16
go.sum
16
go.sum
@@ -14,15 +14,15 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs
|
|||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
||||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
|
||||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
|
||||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package jabber
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
@@ -15,6 +15,8 @@ const (
|
|||||||
goodDictionaryFile string = "./data/good_dictionary.txt"
|
goodDictionaryFile string = "./data/good_dictionary.txt"
|
||||||
badDictionaryFile string = "./data/bad_dictionary.txt"
|
badDictionaryFile string = "./data/bad_dictionary.txt"
|
||||||
dataFile string = "./data/data.bin"
|
dataFile string = "./data/data.bin"
|
||||||
|
Bad bayesian.Class = "Bad"
|
||||||
|
Good bayesian.Class = "Good"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Выдаёт "очки похожести" для данной фразы.
|
// Выдаёт "очки похожести" для данной фразы.
|
||||||
204
internal/jabber/black-whilte_lists.go
Normal file
204
internal/jabber/black-whilte_lists.go
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
package jabber
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/hjson/hjson-go"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReadWhitelist читает и валидирует белые списки пользователей.
|
||||||
|
func (j *Jabber) ReadWhitelist() error {
|
||||||
|
var (
|
||||||
|
whitelistLoaded = false
|
||||||
|
err error
|
||||||
|
executablePath string
|
||||||
|
)
|
||||||
|
|
||||||
|
executablePath, err = os.Executable()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("unable to get current executable path: %w", err)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
whitelistJSONPath := fmt.Sprintf("%s/data/whitelist.json", filepath.Dir(executablePath))
|
||||||
|
|
||||||
|
locations := []string{
|
||||||
|
"~/.buny-jabber-bot-whitelist.json",
|
||||||
|
"~/buny-jabber-bot-whitelist.json",
|
||||||
|
"/etc/buny-jabber-bot-whitelist.json",
|
||||||
|
whitelistJSONPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, location := range locations {
|
||||||
|
fileInfo, err := os.Stat(location)
|
||||||
|
|
||||||
|
// Предполагаем, что файла либо нет, либо мы не можем его прочитать, второе надо бы логгировать, но пока забьём
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Файл белого списка длинноват для белого списка, попробуем следующего кандидата
|
||||||
|
if fileInfo.Size() > 2097152 {
|
||||||
|
log.Warnf("Whitelist file %s is too long for whitelist, skipping", location)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := os.ReadFile(location)
|
||||||
|
|
||||||
|
// Не удалось прочитать, попробуем следующего кандидата
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Skip reading whitelist file %s: %s", location, err)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Исходя из документации, hjson какбы умеет парсить "кривой" json, но парсит его в map-ку.
|
||||||
|
// Интереснее на выходе получить структурку: то есть мы вначале конфиг преобразуем в map-ку, затем эту map-ку
|
||||||
|
// сериализуем в json, а потом json превращаем в структурку. Не очень эффективно, но он и нечасто требуется.
|
||||||
|
var (
|
||||||
|
sampleWhitelist MyWhiteList
|
||||||
|
tmp map[string]interface{}
|
||||||
|
)
|
||||||
|
|
||||||
|
err = hjson.Unmarshal(buf, &tmp)
|
||||||
|
|
||||||
|
// Не удалось распарсить - попробуем следующего кандидата
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Skip parsing whitelist file %s: %s", location, err)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpJSON, err := json.Marshal(tmp)
|
||||||
|
|
||||||
|
// Не удалось преобразовать map-ку в json
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Skip parsing whitelist file %s: %s", location, err)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(tmpJSON, &sampleWhitelist); err != nil {
|
||||||
|
log.Warnf("Skip parsing whitelist file %s: %s", location, err)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
j.WhiteList = sampleWhitelist
|
||||||
|
whitelistLoaded = true
|
||||||
|
|
||||||
|
log.Infof("Using %s as whiteList file", location)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if !whitelistLoaded {
|
||||||
|
return errors.New("whitelist was not loaded") //nolint:goerr113
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadBlacklist читает и валидирует чёрные списки пользователей.
|
||||||
|
func (j *Jabber) ReadBlacklist() error {
|
||||||
|
var (
|
||||||
|
blacklistLoaded = false
|
||||||
|
err error
|
||||||
|
executablePath string
|
||||||
|
)
|
||||||
|
|
||||||
|
executablePath, err = os.Executable()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("unable to get current executable path: %w", err)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
whitelistJSONPath := fmt.Sprintf("%s/data/blacklist.json", filepath.Dir(executablePath))
|
||||||
|
|
||||||
|
locations := []string{
|
||||||
|
"~/.bunyPresense-jabber-bot-blacklist.json",
|
||||||
|
"~/bunyPresense-jabber-bot-blacklist.json",
|
||||||
|
"/etc/bunyPresense-jabber-bot-blacklist.json",
|
||||||
|
whitelistJSONPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, location := range locations {
|
||||||
|
fileInfo, err := os.Stat(location)
|
||||||
|
|
||||||
|
// Предполагаем, что файла либо нет, либо мы не можем его прочитать, второе надо бы логгировать, но пока забьём
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Файл чёрного списка длинноват для чёрного списка, попробуем следующего кандидата
|
||||||
|
if fileInfo.Size() > 16777216 {
|
||||||
|
log.Warnf("Blacklist file %s is too long for blacklist, skipping", location)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := os.ReadFile(location)
|
||||||
|
|
||||||
|
// Не удалось прочитать, попробуем следующего кандидата
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Skip reading blacklist file %s: %s", location, err)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Исходя из документации, hjson какбы умеет парсить "кривой" json, но парсит его в map-ку.
|
||||||
|
// Интереснее на выходе получить структурку: то есть мы вначале конфиг преобразуем в map-ку, затем эту map-ку
|
||||||
|
// сериализуем в json, а потом json превращаем в структурку. Не очень эффективно, но он и нечасто требуется.
|
||||||
|
var (
|
||||||
|
sampleBlacklist MyBlackList
|
||||||
|
tmp map[string]interface{}
|
||||||
|
)
|
||||||
|
|
||||||
|
err = hjson.Unmarshal(buf, &tmp)
|
||||||
|
|
||||||
|
// Не удалось распарсить - попробуем следующего кандидата
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Skip parsing blacklist file %s: %s", location, err)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpJSON, err := json.Marshal(tmp)
|
||||||
|
|
||||||
|
// Не удалось преобразовать map-ку в json
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Skip parsing blacklist file %s: %s", location, err)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(tmpJSON, &sampleBlacklist); err != nil {
|
||||||
|
log.Warnf("Skip parsing whitelist file %s: %s", location, err)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
j.BlackList = sampleBlacklist
|
||||||
|
blacklistLoaded = true
|
||||||
|
|
||||||
|
log.Infof("Using %s as blacklist file", location)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if !blacklistLoaded {
|
||||||
|
return errors.New("blacklist was not loaded") //nolint:goerr113
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -1,26 +1,25 @@
|
|||||||
package main
|
package jabber
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/eleksir/go-xmpp"
|
"github.com/eleksir/go-xmpp"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// bunyPresense производит проверку по бело-чёрным спискам. Если presence пришёл от злодея (из чёрного списка), то
|
// BunyPresense производит проверку по бело-чёрным спискам. Если presence пришёл от злодея (из чёрного списка), то
|
||||||
// отправляет его в бан.
|
// отправляет его в бан.
|
||||||
func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
|
func (j *Jabber) BunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// Если у presence-а есть JID и presence из одной из комнат, в которой мы есть и если его домен в чёрном
|
// Если у presence-а есть JID и presence из одной из комнат, в которой мы есть и если его домен в чёрном
|
||||||
// списке, заносим пидора в список outcast-ов
|
// списке, заносим пидора в список outcast-ов
|
||||||
if v.JID != "" {
|
if v.JID != "" {
|
||||||
// На всякий случай: себя никогда не баним, явным образом
|
// На всякий случай: себя никогда не баним, явным образом
|
||||||
if v.JID == talk.JID() {
|
if v.JID == j.Talk.JID() {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +34,7 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
|
|||||||
goodJid := strings.SplitN(v.JID, "/", 2)[0]
|
goodJid := strings.SplitN(v.JID, "/", 2)[0]
|
||||||
|
|
||||||
// Обрабатываем правила белого списка
|
// Обрабатываем правила белого списка
|
||||||
for _, good := range whiteList.Whitelist {
|
for _, good := range j.WhiteList.Whitelist {
|
||||||
// Глобальный белый список
|
// Глобальный белый список
|
||||||
if good.RoomName == "" {
|
if good.RoomName == "" {
|
||||||
for _, person := range good.Jid {
|
for _, person := range good.Jid {
|
||||||
@@ -65,9 +64,9 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Обрабатываем правила чёрного списка
|
// Обрабатываем правила чёрного списка
|
||||||
for _, cRoom := range roomsConnected {
|
for _, cRoom := range j.RoomsConnected {
|
||||||
if cRoom == room {
|
if cRoom == room {
|
||||||
for _, bEntry := range blackList.Blacklist {
|
for _, bEntry := range j.BlackList.Blacklist {
|
||||||
// Обработаем правила глобального чёрного списка
|
// Обработаем правила глобального чёрного списка
|
||||||
if bEntry.RoomName == "" {
|
if bEntry.RoomName == "" {
|
||||||
for _, jidRegexp := range bEntry.JidRe {
|
for _, jidRegexp := range bEntry.JidRe {
|
||||||
@@ -93,7 +92,7 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
|
|||||||
jidRegexp,
|
jidRegexp,
|
||||||
)
|
)
|
||||||
|
|
||||||
id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type)
|
id, err := j.Squash(room, evilJid, bEntry.ReasonEnable, v.Type)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
@@ -102,7 +101,7 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
|
|||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
@@ -133,7 +132,7 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Баним именно jid
|
// Баним именно jid
|
||||||
id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type)
|
id, err := j.Squash(room, evilJid, bEntry.ReasonEnable, v.Type)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
@@ -142,7 +141,7 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
|
|||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
@@ -177,7 +176,7 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
|
|||||||
jidRegexp,
|
jidRegexp,
|
||||||
)
|
)
|
||||||
|
|
||||||
id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type)
|
id, err := j.Squash(room, evilJid, bEntry.ReasonEnable, v.Type)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
@@ -186,7 +185,7 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
|
|||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
@@ -218,7 +217,7 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Баним именно jid
|
// Баним именно jid
|
||||||
id, err := squash(room, evilJid, bEntry.ReasonEnable, v.Type)
|
id, err := j.Squash(room, evilJid, bEntry.ReasonEnable, v.Type)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
@@ -227,7 +226,7 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
|
|||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
@@ -245,9 +244,9 @@ func bunyPresense(v xmpp.Presence) error { //nolint:gocognit,gocyclo
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// bunyChat производит проверку сообщений участников чата по списку забаненных фраз и в случае нахождения запрещённого
|
// BunyChat производит проверку сообщений участников чата по списку забаненных фраз и в случае нахождения запрещённого
|
||||||
// шаблона банит участника чата.
|
// шаблона банит участника чата.
|
||||||
func bunyChat(v xmpp.Chat) error {
|
func (j *Jabber) BunyChat(v xmpp.Chat) error {
|
||||||
var (
|
var (
|
||||||
room = (strings.SplitN(v.Remote, "/", 2))[0]
|
room = (strings.SplitN(v.Remote, "/", 2))[0]
|
||||||
// nick = (strings.SplitN(v.Remote, "/", 2))[1]
|
// nick = (strings.SplitN(v.Remote, "/", 2))[1]
|
||||||
@@ -255,10 +254,10 @@ func bunyChat(v xmpp.Chat) error {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Действовать мы можем только в рамках тех комнат, где явно присуствуем.
|
// Действовать мы можем только в рамках тех комнат, где явно присуствуем.
|
||||||
for _, cRoom := range roomsConnected {
|
for _, cRoom := range j.RoomsConnected {
|
||||||
if cRoom == room {
|
if cRoom == room {
|
||||||
// Перебирём правила чёрных списков.
|
// Перебирём правила чёрных списков.
|
||||||
for _, bEntry := range blackList.Blacklist {
|
for _, bEntry := range j.BlackList.Blacklist {
|
||||||
// Обработаем правила глобального чёрного списка
|
// Обработаем правила глобального чёрного списка
|
||||||
if bEntry.RoomName == "" {
|
if bEntry.RoomName == "" {
|
||||||
for _, phraseRegexp := range bEntry.PhraseRe {
|
for _, phraseRegexp := range bEntry.PhraseRe {
|
||||||
@@ -277,7 +276,7 @@ func bunyChat(v xmpp.Chat) error {
|
|||||||
log.Debugf("Checking phrase %s vs room %s blacklist regex %s", v.Text, room, phraseRegexp)
|
log.Debugf("Checking phrase %s vs room %s blacklist regex %s", v.Text, room, phraseRegexp)
|
||||||
|
|
||||||
if re.MatchString(v.Text) {
|
if re.MatchString(v.Text) {
|
||||||
realJID := getRealJIDfromNick(v.Remote)
|
realJID := j.GetRealJIDfromNick(v.Remote)
|
||||||
|
|
||||||
log.Warnf(
|
log.Warnf(
|
||||||
"Hammer falls on %s (%s): phrase matches with global blacklist entry: %s vs %s",
|
"Hammer falls on %s (%s): phrase matches with global blacklist entry: %s vs %s",
|
||||||
@@ -287,14 +286,14 @@ func bunyChat(v xmpp.Chat) error {
|
|||||||
phraseRegexp,
|
phraseRegexp,
|
||||||
)
|
)
|
||||||
|
|
||||||
if id, err := squash(room, realJID, bEntry.ReasonEnable, v.Type); err != nil {
|
if id, err := j.Squash(room, realJID, bEntry.ReasonEnable, v.Type); err != nil {
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
"unable to ban user: id=%s, err=%w",
|
"unable to ban user: id=%s, err=%w",
|
||||||
id,
|
id,
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
@@ -320,7 +319,7 @@ func bunyChat(v xmpp.Chat) error {
|
|||||||
log.Debugf("Checking phrase %s vs room %s blacklist regex %s", v.Text, room, phraseRegexp)
|
log.Debugf("Checking phrase %s vs room %s blacklist regex %s", v.Text, room, phraseRegexp)
|
||||||
|
|
||||||
if re.MatchString(v.Text) {
|
if re.MatchString(v.Text) {
|
||||||
realJID := getRealJIDfromNick(v.Remote)
|
realJID := j.GetRealJIDfromNick(v.Remote)
|
||||||
|
|
||||||
log.Warnf(
|
log.Warnf(
|
||||||
"Hammer falls on %s (%s): phrase matches with room blacklist entry: %s vs %s",
|
"Hammer falls on %s (%s): phrase matches with room blacklist entry: %s vs %s",
|
||||||
@@ -330,14 +329,14 @@ func bunyChat(v xmpp.Chat) error {
|
|||||||
phraseRegexp,
|
phraseRegexp,
|
||||||
)
|
)
|
||||||
|
|
||||||
if id, err := squash(room, realJID, bEntry.ReasonEnable, v.Type); err != nil {
|
if id, err := j.Squash(room, realJID, bEntry.ReasonEnable, v.Type); err != nil {
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
"unable to ban user: id=%s, err=%w",
|
"unable to ban user: id=%s, err=%w",
|
||||||
id,
|
id,
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
@@ -347,7 +346,7 @@ func bunyChat(v xmpp.Chat) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Если включено, проверяем фразу на КАПС.
|
// Если включено, проверяем фразу на КАПС.
|
||||||
for _, channel := range config.Jabber.Channels {
|
for _, channel := range j.C.Jabber.Channels {
|
||||||
if channel.Name == room && channel.AllCaps.Enabled {
|
if channel.Name == room && channel.AllCaps.Enabled {
|
||||||
// Нормализуем строку и вырежем из неё пробелы
|
// Нормализуем строку и вырежем из неё пробелы
|
||||||
normPhrase := strings.ReplaceAll(nString(v.Text), " ", "")
|
normPhrase := strings.ReplaceAll(nString(v.Text), " ", "")
|
||||||
@@ -357,8 +356,8 @@ func bunyChat(v xmpp.Chat) error {
|
|||||||
normPhraseUpper := strings.ReplaceAll(nStringUpper(v.Text), " ", "")
|
normPhraseUpper := strings.ReplaceAll(nStringUpper(v.Text), " ", "")
|
||||||
|
|
||||||
if normPhrase == normPhraseUpper {
|
if normPhrase == normPhraseUpper {
|
||||||
realJID := getRealJIDfromNick(v.Remote)
|
realJID := j.GetRealJIDfromNick(v.Remote)
|
||||||
id, err := squash(room, realJID, false, v.Type)
|
id, err := j.Squash(room, realJID, false, v.Type)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
@@ -367,7 +366,7 @@ func bunyChat(v xmpp.Chat) error {
|
|||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -381,74 +380,4 @@ func bunyChat(v xmpp.Chat) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// squash банит указанный jid в указанной комнате.
|
|
||||||
// reasonEnable указывает, надо ли писать дату автобана в банлисте в поле reason (это единственная причина, в которую
|
|
||||||
// умеет бот).
|
|
||||||
func squash(room, jid string, reasonEnable bool, vType string) (string, error) {
|
|
||||||
var (
|
|
||||||
id string
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
|
|
||||||
if config.Jabber.BanPhrasesEnable {
|
|
||||||
phrase := randomPhrase(config.Jabber.BanPhrases)
|
|
||||||
|
|
||||||
if _, err = talk.Send(
|
|
||||||
xmpp.Chat{ //nolint:exhaustruct
|
|
||||||
Remote: room,
|
|
||||||
Text: phrase,
|
|
||||||
Type: vType,
|
|
||||||
},
|
|
||||||
); err != nil {
|
|
||||||
err = fmt.Errorf("unable to send phrase to room %s: %w", room, err)
|
|
||||||
|
|
||||||
// Здесь возвращаем nil, т.к. за нас ошибку залоггирует код выше
|
|
||||||
return id, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://xmpp.org/extensions/xep-0045.html#ban баним вот таким сообщением
|
|
||||||
ban := "<item affiliation='outcast' jid='" + jid + "'>"
|
|
||||||
|
|
||||||
if reasonEnable {
|
|
||||||
var t = time.Now()
|
|
||||||
ban += fmt.Sprintf(
|
|
||||||
"<reason>autoban at %04d.%02d.%02d %02d:%02d:%02d</reason>",
|
|
||||||
t.Year(),
|
|
||||||
t.Month(),
|
|
||||||
t.Day(),
|
|
||||||
t.Hour(),
|
|
||||||
t.Minute(),
|
|
||||||
t.Second(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
ban += "<reason />"
|
|
||||||
}
|
|
||||||
|
|
||||||
ban += "</item>"
|
|
||||||
|
|
||||||
// Выжидаем некоторое время перед баном. А то можно настолько рано забанить, что сервер не внесёт злодея в банлист
|
|
||||||
// комнаты и пришлёт affiliation: none вместо affiliation: outcast.
|
|
||||||
if config.Jabber.BanDelay > 0 {
|
|
||||||
time.Sleep(time.Duration(config.Jabber.BanDelay) * time.Millisecond)
|
|
||||||
}
|
|
||||||
|
|
||||||
if id, err = talk.RawInformationQuery(
|
|
||||||
talk.JID(),
|
|
||||||
room,
|
|
||||||
"ban1",
|
|
||||||
xmpp.IQTypeSet,
|
|
||||||
"http://jabber.org/protocol/muc#admin",
|
|
||||||
ban,
|
|
||||||
); err != nil {
|
|
||||||
err = fmt.Errorf(
|
|
||||||
"unable to ban user: id=%s, err=%w",
|
|
||||||
id,
|
|
||||||
err,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return id, err
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package jabber
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package jabber
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -10,29 +10,29 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// cmd парсит команды из чятика.
|
// Cmd парсит команды из чятика.
|
||||||
func cmd(v xmpp.Chat) error {
|
func (j *Jabber) Cmd(v xmpp.Chat) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case v.Text == fmt.Sprintf("%shelp", config.CSign) || v.Text == fmt.Sprintf("%sпомощь", config.CSign):
|
case v.Text == fmt.Sprintf("%shelp", j.C.CSign) || v.Text == fmt.Sprintf("%sпомощь", j.C.CSign):
|
||||||
var (
|
var (
|
||||||
answer string
|
answer string
|
||||||
chosenOneTalks = false
|
chosenOneTalks = false
|
||||||
)
|
)
|
||||||
|
|
||||||
realJID := getRealJIDfromNick(v.Remote)
|
realJID := j.GetRealJIDfromNick(v.Remote)
|
||||||
|
|
||||||
for _, master := range config.Jabber.BotMasters {
|
for _, master := range j.C.Jabber.BotMasters {
|
||||||
if (strings.SplitN(realJID, "/", 2))[0] == master {
|
if (strings.SplitN(realJID, "/", 2))[0] == master {
|
||||||
chosenOneTalks = true
|
chosenOneTalks = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if chosenOneTalks {
|
if chosenOneTalks {
|
||||||
answer = fmt.Sprintf("%sпомощь - этот список команд\n", config.CSign)
|
answer = fmt.Sprintf("%sпомощь - этот список команд\n", j.C.CSign)
|
||||||
answer += fmt.Sprintf("%shelp - this commands list\n", config.CSign)
|
answer += fmt.Sprintf("%shelp - this commands list\n", j.C.CSign)
|
||||||
answer += fmt.Sprintf("%srehash - reload white and black lists", config.CSign)
|
answer += fmt.Sprintf("%srehash - reload white and black lists", j.C.CSign)
|
||||||
} else {
|
} else {
|
||||||
answer = "Ничем помочь не могу. Луна не светит на тебя."
|
answer = "Ничем помочь не могу. Луна не светит на тебя."
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ func cmd(v xmpp.Chat) error {
|
|||||||
dest = (strings.SplitN(v.Remote, "/", 2))[0]
|
dest = (strings.SplitN(v.Remote, "/", 2))[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := talk.Send(
|
if _, err := j.Talk.Send(
|
||||||
xmpp.Chat{ //nolint:exhaustruct
|
xmpp.Chat{ //nolint:exhaustruct
|
||||||
Remote: dest,
|
Remote: dest,
|
||||||
Text: strings.TrimSpace(answer),
|
Text: strings.TrimSpace(answer),
|
||||||
@@ -55,7 +55,7 @@ func cmd(v xmpp.Chat) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case v.Text == fmt.Sprintf("%srehash", config.CSign): //nolint:wsl
|
case v.Text == fmt.Sprintf("%srehash", j.C.CSign): //nolint:wsl
|
||||||
/* Эта команда может прилетать из приватной беседы с realjid-ом, из приватной беседы с chat-nick-ом, а также из
|
/* Эта команда может прилетать из приватной беседы с realjid-ом, из приватной беседы с chat-nick-ом, а также из
|
||||||
* чятика.
|
* чятика.
|
||||||
* Groupchat мы можем определить по v.Type (groupchat) и тогда понятно что делать.
|
* Groupchat мы можем определить по v.Type (groupchat) и тогда понятно что делать.
|
||||||
@@ -72,9 +72,9 @@ func cmd(v xmpp.Chat) error {
|
|||||||
listsLoaded = true
|
listsLoaded = true
|
||||||
)
|
)
|
||||||
|
|
||||||
realJID := getRealJIDfromNick(v.Remote)
|
realJID := j.GetRealJIDfromNick(v.Remote)
|
||||||
|
|
||||||
for _, master := range config.Jabber.BotMasters {
|
for _, master := range j.C.Jabber.BotMasters {
|
||||||
if (strings.SplitN(realJID, "/", 2))[0] == master {
|
if (strings.SplitN(realJID, "/", 2))[0] == master {
|
||||||
chosenOneTalks = true
|
chosenOneTalks = true
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ func cmd(v xmpp.Chat) error {
|
|||||||
if !chosenOneTalks {
|
if !chosenOneTalks {
|
||||||
log.Infof(
|
log.Infof(
|
||||||
"Command %srehash given by non-bot_master user %s(%s), ignoring",
|
"Command %srehash given by non-bot_master user %s(%s), ignoring",
|
||||||
config.CSign,
|
j.C.CSign,
|
||||||
realJID,
|
realJID,
|
||||||
v.Remote,
|
v.Remote,
|
||||||
)
|
)
|
||||||
@@ -91,7 +91,7 @@ func cmd(v xmpp.Chat) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := readWhitelist(); err != nil {
|
if err := j.ReadWhitelist(); err != nil {
|
||||||
listsLoaded = false
|
listsLoaded = false
|
||||||
|
|
||||||
var msg xmpp.Chat
|
var msg xmpp.Chat
|
||||||
@@ -99,12 +99,12 @@ func cmd(v xmpp.Chat) error {
|
|||||||
msg.Type = "chat" // private message
|
msg.Type = "chat" // private message
|
||||||
msg.Text = fmt.Sprint(err)
|
msg.Text = fmt.Sprint(err)
|
||||||
|
|
||||||
if _, err := talk.Send(msg); err != nil {
|
if _, err := j.Talk.Send(msg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := readBlacklist(); err != nil {
|
if err := j.ReadBlacklist(); err != nil {
|
||||||
listsLoaded = false
|
listsLoaded = false
|
||||||
|
|
||||||
var msg xmpp.Chat
|
var msg xmpp.Chat
|
||||||
@@ -112,7 +112,7 @@ func cmd(v xmpp.Chat) error {
|
|||||||
msg.Type = "chat" // private message
|
msg.Type = "chat" // private message
|
||||||
msg.Text = fmt.Sprint(err)
|
msg.Text = fmt.Sprint(err)
|
||||||
|
|
||||||
if _, err := talk.Send(msg); err != nil {
|
if _, err := j.Talk.Send(msg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,7 +125,7 @@ func cmd(v xmpp.Chat) error {
|
|||||||
msg.Type = v.Type
|
msg.Type = v.Type
|
||||||
msg.Text = "Сделано"
|
msg.Text = "Сделано"
|
||||||
|
|
||||||
if _, err := talk.Send(msg); err != nil {
|
if _, err := j.Talk.Send(msg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,16 +133,16 @@ func cmd(v xmpp.Chat) error {
|
|||||||
room := (strings.SplitN(v.Remote, "/", 2))[0]
|
room := (strings.SplitN(v.Remote, "/", 2))[0]
|
||||||
|
|
||||||
// Реагировать на приватную команду "из комнаты", только если бот в комнате
|
// Реагировать на приватную команду "из комнаты", только если бот в комнате
|
||||||
if slices.Contains(roomsConnected, room) {
|
if slices.Contains(j.RoomsConnected, room) {
|
||||||
var (
|
var (
|
||||||
chosenOneTalks = false
|
chosenOneTalks = false
|
||||||
listsLoaded = true
|
listsLoaded = true
|
||||||
)
|
)
|
||||||
|
|
||||||
// Реагировать на rehash только если собеседник является bot master-ом
|
// Реагировать на rehash только если собеседник является bot master-ом
|
||||||
realJID := getRealJIDfromNick(v.Remote)
|
realJID := j.GetRealJIDfromNick(v.Remote)
|
||||||
|
|
||||||
for _, master := range config.Jabber.BotMasters {
|
for _, master := range j.C.Jabber.BotMasters {
|
||||||
if (strings.SplitN(realJID, "/", 2))[0] == master {
|
if (strings.SplitN(realJID, "/", 2))[0] == master {
|
||||||
chosenOneTalks = true
|
chosenOneTalks = true
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,7 @@ func cmd(v xmpp.Chat) error {
|
|||||||
if !chosenOneTalks {
|
if !chosenOneTalks {
|
||||||
log.Infof(
|
log.Infof(
|
||||||
"Command %srehash given by non-bot_master user %s(%s), ignoring",
|
"Command %srehash given by non-bot_master user %s(%s), ignoring",
|
||||||
config.CSign,
|
j.C.CSign,
|
||||||
realJID,
|
realJID,
|
||||||
v.Remote,
|
v.Remote,
|
||||||
)
|
)
|
||||||
@@ -159,7 +159,7 @@ func cmd(v xmpp.Chat) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := readWhitelist(); err != nil {
|
if err := j.ReadWhitelist(); err != nil {
|
||||||
listsLoaded = false
|
listsLoaded = false
|
||||||
|
|
||||||
var msg xmpp.Chat
|
var msg xmpp.Chat
|
||||||
@@ -167,12 +167,12 @@ func cmd(v xmpp.Chat) error {
|
|||||||
msg.Type = v.Type
|
msg.Type = v.Type
|
||||||
msg.Text = fmt.Sprint(err)
|
msg.Text = fmt.Sprint(err)
|
||||||
|
|
||||||
if _, err := talk.Send(msg); err != nil {
|
if _, err := j.Talk.Send(msg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := readBlacklist(); err != nil {
|
if err := j.ReadBlacklist(); err != nil {
|
||||||
listsLoaded = false
|
listsLoaded = false
|
||||||
|
|
||||||
var msg xmpp.Chat
|
var msg xmpp.Chat
|
||||||
@@ -180,7 +180,7 @@ func cmd(v xmpp.Chat) error {
|
|||||||
msg.Type = v.Type
|
msg.Type = v.Type
|
||||||
msg.Text = fmt.Sprint(err)
|
msg.Text = fmt.Sprint(err)
|
||||||
|
|
||||||
if _, err := talk.Send(msg); err != nil {
|
if _, err := j.Talk.Send(msg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,7 +191,7 @@ func cmd(v xmpp.Chat) error {
|
|||||||
msg.Type = v.Type
|
msg.Type = v.Type
|
||||||
msg.Text = "Сделано"
|
msg.Text = "Сделано"
|
||||||
|
|
||||||
if _, err := talk.Send(msg); err != nil {
|
if _, err := j.Talk.Send(msg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package jabber
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -15,9 +15,9 @@ import (
|
|||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
// parseEvent парсит ивенты, прилетающие из модуля xmpp (изменения presence, фразы участников, ошибки).
|
// ParseEvent парсит ивенты, прилетающие из модуля xmpp (изменения presence, фразы участников, ошибки).
|
||||||
func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
func (j *Jabber) ParseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
||||||
lastServerActivity = time.Now().Unix()
|
j.LastServerActivity = time.Now().Unix()
|
||||||
|
|
||||||
switch v := e.(type) {
|
switch v := e.(type) {
|
||||||
// Сообщение в чяти
|
// Сообщение в чяти
|
||||||
@@ -40,28 +40,28 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
|
|
||||||
log.Debugf("Message from public chat: %s", v.Text)
|
log.Debugf("Message from public chat: %s", v.Text)
|
||||||
|
|
||||||
if nick == getBotNickFromRoomConfig(room) {
|
if nick == j.GetBotNickFromRoomConfig(room) {
|
||||||
log.Debug("Skipping message from myself")
|
log.Debug("Skipping message from myself")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cmd(v); err != nil {
|
if err := j.Cmd(v); err != nil {
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := bunyChat(v); err != nil {
|
if err := j.BunyChat(v); err != nil {
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
lastActivity = lastServerActivity
|
j.LastActivity = j.LastServerActivity
|
||||||
|
|
||||||
if muc, _ := strings.CutSuffix(v.Remote, "/"); muc != "" {
|
if muc, _ := strings.CutSuffix(v.Remote, "/"); muc != "" {
|
||||||
lastMucActivity.Set(muc, lastServerActivity)
|
j.LastMucActivity.Set(muc, j.LastServerActivity)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Приватный чятик
|
// Приватный чятик
|
||||||
@@ -71,13 +71,13 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
// eleksir@jabber.ru/array.lan - это если мы работаем через ростер
|
// eleksir@jabber.ru/array.lan - это если мы работаем через ростер
|
||||||
log.Debugf("Private message: %s", v.Text)
|
log.Debugf("Private message: %s", v.Text)
|
||||||
|
|
||||||
if err := cmd(v); err != nil {
|
if err := j.Cmd(v); err != nil {
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
lastActivity = lastServerActivity
|
j.LastActivity = j.LastServerActivity
|
||||||
|
|
||||||
// Внезапно, ошибки. По идее они должны ассоциироваться с отправляемыми сообщениями, но по ходу это
|
// Внезапно, ошибки. По идее они должны ассоциироваться с отправляемыми сообщениями, но по ходу это
|
||||||
// не реализовано, поэтому мы получаем ошибки в форме отдельного чятика
|
// не реализовано, поэтому мы получаем ошибки в форме отдельного чятика
|
||||||
@@ -102,13 +102,13 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
log.Debug("Looks like IQ get query")
|
log.Debug("Looks like IQ get query")
|
||||||
|
|
||||||
if muc, _ := strings.CutSuffix(v.To, "/"); muc != "" {
|
if muc, _ := strings.CutSuffix(v.To, "/"); muc != "" {
|
||||||
if slices.Contains(roomsConnected, muc) {
|
if slices.Contains(j.RoomsConnected, muc) {
|
||||||
lastMucActivity.Set(muc, lastServerActivity)
|
j.LastMucActivity.Set(muc, j.LastServerActivity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
iqStruct jabberSimpleIqGetQuery
|
iqStruct JabberSimpleIqGetQuery
|
||||||
parseError bool
|
parseError bool
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
case "jabber:iq:version":
|
case "jabber:iq:version":
|
||||||
log.Infof("Got IQ get request for version from %s", v.From)
|
log.Infof("Got IQ get request for version from %s", v.From)
|
||||||
|
|
||||||
if id, err := talk.IqVersionResponse(
|
if id, err := j.Talk.IqVersionResponse(
|
||||||
v,
|
v,
|
||||||
"buny-jabber-bot",
|
"buny-jabber-bot",
|
||||||
"1.dev",
|
"1.dev",
|
||||||
@@ -131,7 +131,7 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -142,14 +142,14 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
case "urn:xmpp:ping":
|
case "urn:xmpp:ping":
|
||||||
log.Infof("Got IQ get request for pong from %s", v.From)
|
log.Infof("Got IQ get request for pong from %s", v.From)
|
||||||
|
|
||||||
if id, err := talk.PingResponse(v); err != nil {
|
if id, err := j.Talk.PingResponse(v); err != nil {
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
"unable to send pong to jabber server: id=%s, err=%w",
|
"unable to send pong to jabber server: id=%s, err=%w",
|
||||||
id,
|
id,
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -161,14 +161,14 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
case "jabber:iq:last":
|
case "jabber:iq:last":
|
||||||
log.Infof("Got IQ get last activity time request from %s", v.From)
|
log.Infof("Got IQ get last activity time request from %s", v.From)
|
||||||
|
|
||||||
if id, err := talk.JabberIqLastResponse(v, lastActivity); err != nil {
|
if id, err := j.Talk.JabberIqLastResponse(v, j.LastActivity); err != nil {
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
"unable to send last activity time to jabber server: id=%s, err=%w",
|
"unable to send last activity time to jabber server: id=%s, err=%w",
|
||||||
id,
|
id,
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -187,7 +187,7 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
answer += "<feature var=\"http://jabber.org/protocol/disco#info\" />"
|
answer += "<feature var=\"http://jabber.org/protocol/disco#info\" />"
|
||||||
answer += "</query>"
|
answer += "</query>"
|
||||||
|
|
||||||
if id, err := talk.RawInformation(
|
if id, err := j.Talk.RawInformation(
|
||||||
v.To,
|
v.To,
|
||||||
v.From,
|
v.From,
|
||||||
v.ID,
|
v.ID,
|
||||||
@@ -200,7 +200,7 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -211,7 +211,7 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
case xmpp.XMPPNS_DISCO_ITEMS:
|
case xmpp.XMPPNS_DISCO_ITEMS:
|
||||||
log.Infof("Got IQ get disco#items request from %s, answer service unavailable", v.From)
|
log.Infof("Got IQ get disco#items request from %s, answer service unavailable", v.From)
|
||||||
|
|
||||||
if _, err := talk.ErrorServiceUnavailable(
|
if _, err := j.Talk.ErrorServiceUnavailable(
|
||||||
v,
|
v,
|
||||||
"http://jabber.org/protocol/disco#info",
|
"http://jabber.org/protocol/disco#info",
|
||||||
"http://jabber.org/protocol/commands",
|
"http://jabber.org/protocol/commands",
|
||||||
@@ -222,7 +222,7 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -242,21 +242,21 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
|
|
||||||
// Попробуем распарсить входящий запрос как urn:xmpp:time
|
// Попробуем распарсить входящий запрос как urn:xmpp:time
|
||||||
if parseError {
|
if parseError {
|
||||||
var iqStruct jabberTimeIqGetQuery
|
var iqStruct JabberTimeIqGetQuery
|
||||||
|
|
||||||
if err := xml.Unmarshal(v.Query, &iqStruct); err == nil {
|
if err := xml.Unmarshal(v.Query, &iqStruct); err == nil {
|
||||||
switch iqStruct.Xmlns {
|
switch iqStruct.Xmlns {
|
||||||
case "urn:xmpp:time":
|
case "urn:xmpp:time":
|
||||||
log.Infof("Got IQ get time request from %s", v.From)
|
log.Infof("Got IQ get time request from %s", v.From)
|
||||||
|
|
||||||
if id, err := talk.UrnXMPPTimeResponse(v, "+00:00"); err != nil {
|
if id, err := j.Talk.UrnXMPPTimeResponse(v, "+00:00"); err != nil {
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
"unable to send urn:xmpp:time to jabber server: id=%s, err=%w",
|
"unable to send urn:xmpp:time to jabber server: id=%s, err=%w",
|
||||||
id,
|
id,
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -276,14 +276,14 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
|
|
||||||
// Попробуем распарсить входящий запрос как http://jabber.org/protocol/pubsub
|
// Попробуем распарсить входящий запрос как http://jabber.org/protocol/pubsub
|
||||||
if parseError {
|
if parseError {
|
||||||
var iqStruct jabberPubsubIQGetQuery
|
var iqStruct JabberPubsubIQGetQuery
|
||||||
|
|
||||||
if err := xml.Unmarshal(v.Query, &iqStruct); err == nil {
|
if err := xml.Unmarshal(v.Query, &iqStruct); err == nil {
|
||||||
switch iqStruct.Xmlns {
|
switch iqStruct.Xmlns {
|
||||||
case xmpp.XMPPNS_PUBSUB:
|
case xmpp.XMPPNS_PUBSUB:
|
||||||
log.Infof("Got IQ get pubsub request from %s, answer feature unimplemented", v.From)
|
log.Infof("Got IQ get pubsub request from %s, answer feature unimplemented", v.From)
|
||||||
|
|
||||||
if id, err := talk.ErrorNotImplemented(
|
if id, err := j.Talk.ErrorNotImplemented(
|
||||||
v,
|
v,
|
||||||
"http://jabber.org/protocol/pubsub#errors",
|
"http://jabber.org/protocol/pubsub#errors",
|
||||||
"subscribe",
|
"subscribe",
|
||||||
@@ -293,7 +293,7 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -314,19 +314,19 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
// Предполагается, что такие респонсы должны приходить только для пинга без серверной оптимизации.
|
// Предполагается, что такие респонсы должны приходить только для пинга без серверной оптимизации.
|
||||||
// Хотя идейно мы не поддерживаем работу без серверной оптимизации, но на пинг ответим, нам несложно.
|
// Хотя идейно мы не поддерживаем работу без серверной оптимизации, но на пинг ответим, нам несложно.
|
||||||
if parseError {
|
if parseError {
|
||||||
var iqStruct jabberIqPing
|
var iqStruct JabberIqPing
|
||||||
|
|
||||||
if err := xml.Unmarshal(v.Query, &iqStruct); err == nil {
|
if err := xml.Unmarshal(v.Query, &iqStruct); err == nil {
|
||||||
log.Debugf("Got IQ get request (actually, response) for MUC Self-Ping from %s", v.From)
|
log.Debugf("Got IQ get request (actually, response) for MUC Self-Ping from %s", v.From)
|
||||||
|
|
||||||
if id, err := talk.PingResponse(v); err != nil {
|
if id, err := j.Talk.PingResponse(v); err != nil {
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
"unable to send pong to jabber server: id=%s, err=%w",
|
"unable to send pong to jabber server: id=%s, err=%w",
|
||||||
id,
|
id,
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -343,28 +343,28 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
|
|
||||||
case xmpp.IQTypeResult:
|
case xmpp.IQTypeResult:
|
||||||
if muc, _ := strings.CutSuffix(v.To, "/"); muc != "" {
|
if muc, _ := strings.CutSuffix(v.To, "/"); muc != "" {
|
||||||
if slices.Contains(roomsConnected, muc) {
|
if slices.Contains(j.RoomsConnected, muc) {
|
||||||
lastMucActivity.Set(muc, lastServerActivity)
|
j.LastMucActivity.Set(muc, j.LastServerActivity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
// Похоже на pong от сервера (по стандарту в ответе нету query, но go-xmpp нам подсовывает это)
|
// Похоже на pong от сервера (по стандарту в ответе нету query, но go-xmpp нам подсовывает это)
|
||||||
case v.From == config.Jabber.Server && v.To == talk.JID() && string(v.Query) == "<XMLElement></XMLElement>":
|
case v.From == j.C.Jabber.Server && v.To == j.Talk.JID() && string(v.Query) == "<XMLElement></XMLElement>":
|
||||||
log.Debugf("Got S2C pong answer from %s to %s", v.From, v.To)
|
log.Debugf("Got S2C pong answer from %s to %s", v.From, v.To)
|
||||||
serverPingTimestampRx = time.Now().Unix() //nolint:wsl
|
j.ServerPingTimestampRx = time.Now().Unix() //nolint:wsl
|
||||||
|
|
||||||
// Похоже на понг второй стадии xep-0410 MUC-Ping-а, который у нас не реализован
|
// Похоже на понг второй стадии xep-0410 MUC-Ping-а, который у нас не реализован
|
||||||
case v.To == talk.JID() && string(v.Query) == "<XMLElement></XMLElement>":
|
case v.To == j.Talk.JID() && string(v.Query) == "<XMLElement></XMLElement>":
|
||||||
mucNameMatch := slices.Contains(roomsConnected, v.From)
|
mucNameMatch := slices.Contains(j.RoomsConnected, v.From)
|
||||||
|
|
||||||
if mucNameMatch {
|
if mucNameMatch {
|
||||||
log.Debugf("Got server-optimized MUC pong answer (xep-0410) from %s to %s", v.From, v.To)
|
log.Debugf("Got server-optimized MUC pong answer (xep-0410) from %s to %s", v.From, v.To)
|
||||||
} else {
|
} else {
|
||||||
mucNickMatch := false
|
mucNickMatch := false
|
||||||
|
|
||||||
for _, room := range roomsConnected {
|
for _, room := range j.RoomsConnected {
|
||||||
mucNick := fmt.Sprintf("%s/%s", room, getBotNickFromRoomConfig(room))
|
mucNick := fmt.Sprintf("%s/%s", room, j.GetBotNickFromRoomConfig(room))
|
||||||
|
|
||||||
if v.From == mucNick {
|
if v.From == mucNick {
|
||||||
mucNickMatch = true
|
mucNickMatch = true
|
||||||
@@ -383,15 +383,15 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Подтверждение бана
|
// Подтверждение бана
|
||||||
case v.To == talk.JID() && v.ID == "ban1":
|
case v.To == j.Talk.JID() && v.ID == "ban1":
|
||||||
mucNickMatch := false
|
mucNickMatch := false
|
||||||
|
|
||||||
// Если ник, которому предназначается сообщение, совпадает с ником, из конфига бота (глобального или для
|
// Если ник, которому предназначается сообщение, совпадает с ником, из конфига бота (глобального или для
|
||||||
// комнаты), то считаем, что мы есть в этой комнате. Потому что в противном случае в roomsConnected не
|
// комнаты), то считаем, что мы есть в этой комнате. Потому что в противном случае в roomsConnected не
|
||||||
// будет искомой комнаты и мы не сможем составить ник бота, чтобы сравнить его с тем, кому адресовано
|
// будет искомой комнаты и мы не сможем составить ник бота, чтобы сравнить его с тем, кому адресовано
|
||||||
// уведомление.
|
// уведомление.
|
||||||
for _, room := range roomsConnected {
|
for _, room := range j.RoomsConnected {
|
||||||
mucNick := fmt.Sprintf("%s/%s", room, getBotNickFromRoomConfig(room))
|
mucNick := fmt.Sprintf("%s/%s", room, j.GetBotNickFromRoomConfig(room))
|
||||||
|
|
||||||
if v.To == mucNick {
|
if v.To == mucNick {
|
||||||
mucNickMatch = true
|
mucNickMatch = true
|
||||||
@@ -403,7 +403,7 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
// Формально, ответ должен парситься как пустой result и совпадать с типом jabberSimpleIqGetQuery
|
// Формально, ответ должен парситься как пустой result и совпадать с типом jabberSimpleIqGetQuery
|
||||||
// Ответ приходит с 2 xmlns, похоже, он парсится неправильно в go-xmpp.
|
// Ответ приходит с 2 xmlns, похоже, он парсится неправильно в go-xmpp.
|
||||||
// TODO: после исправления go-xmpp, надо исправить это тут
|
// TODO: после исправления go-xmpp, надо исправить это тут
|
||||||
var iqStruct jabberSimpleIqGetQuery
|
var iqStruct JabberSimpleIqGetQuery
|
||||||
|
|
||||||
if err := xml.Unmarshal(v.Query, &iqStruct); err == nil {
|
if err := xml.Unmarshal(v.Query, &iqStruct); err == nil {
|
||||||
if iqStruct.Xmlns == "http://jabber.org/protocol/muc#admin" && iqStruct.Text == "" {
|
if iqStruct.Xmlns == "http://jabber.org/protocol/muc#admin" && iqStruct.Text == "" {
|
||||||
@@ -432,14 +432,14 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
// Этот бот не управляется со стороны сервера, поэтому все попытки порулить игнорируем
|
// Этот бот не управляется со стороны сервера, поэтому все попытки порулить игнорируем
|
||||||
case xmpp.IQTypeSet:
|
case xmpp.IQTypeSet:
|
||||||
if muc, _ := strings.CutSuffix(v.To, "/"); muc != "" {
|
if muc, _ := strings.CutSuffix(v.To, "/"); muc != "" {
|
||||||
if slices.Contains(roomsConnected, muc) {
|
if slices.Contains(j.RoomsConnected, muc) {
|
||||||
lastMucActivity.Set(muc, lastServerActivity)
|
j.LastMucActivity.Set(muc, j.LastServerActivity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Got an IQ request for set something. Answer not implemented")
|
log.Info("Got an IQ request for set something. Answer not implemented")
|
||||||
|
|
||||||
if id, err := talk.ErrorNotImplemented(
|
if id, err := j.Talk.ErrorNotImplemented(
|
||||||
v,
|
v,
|
||||||
"http://jabber.org/protocol/commands",
|
"http://jabber.org/protocol/commands",
|
||||||
xmpp.IQTypeSet,
|
xmpp.IQTypeSet,
|
||||||
@@ -450,7 +450,7 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -462,18 +462,18 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
// Если сервер не хочет пинговаться и отвечает ошибкой на пинг, то наверно он не умеет в пинги,
|
// Если сервер не хочет пинговаться и отвечает ошибкой на пинг, то наверно он не умеет в пинги,
|
||||||
// хотя если мы его пингуем, значит он анонсировал такой capability. Вот, засранец!
|
// хотя если мы его пингуем, значит он анонсировал такой capability. Вот, засранец!
|
||||||
var (
|
var (
|
||||||
iqPingStruct jabberIqPing
|
iqPingStruct JabberIqPing
|
||||||
parseError = true
|
parseError = true
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := xml.Unmarshal(v.Query, &iqPingStruct); err == nil {
|
if err := xml.Unmarshal(v.Query, &iqPingStruct); err == nil {
|
||||||
if iqPingStruct.Xmlns == "urn:xmpp:ping" {
|
if iqPingStruct.Xmlns == "urn:xmpp:ping" {
|
||||||
if v.From == config.Jabber.Server {
|
if v.From == j.C.Jabber.Server {
|
||||||
msg := "Server announced that it can answer c2s ping, but gives us an error to such query, "
|
msg := "Server announced that it can answer c2s ping, but gives us an error to such query, "
|
||||||
msg += "fallback to keepalive whitespace pings"
|
msg += "fallback to keepalive whitespace pings"
|
||||||
log.Error(msg)
|
log.Error(msg)
|
||||||
|
|
||||||
serverCapsList.Set("urn:xmpp:ping", false)
|
j.ServerCapsList.Set("urn:xmpp:ping", false)
|
||||||
} else {
|
} else {
|
||||||
log.Errorf("Got 'ping unsupported' message from: %s to: %s", v.From, v.To)
|
log.Errorf("Got 'ping unsupported' message from: %s to: %s", v.From, v.To)
|
||||||
}
|
}
|
||||||
@@ -487,30 +487,30 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
|
|
||||||
// Это у нас пинг xep-0410 и мы не в комнате, предполагается, что надо бы заджойниться
|
// Это у нас пинг xep-0410 и мы не в комнате, предполагается, что надо бы заджойниться
|
||||||
if parseError {
|
if parseError {
|
||||||
var iqErrorCancelNotAcceptable jabberIqErrorCancelNotAcceptable
|
var iqErrorCancelNotAcceptable JabberIqErrorCancelNotAcceptable
|
||||||
|
|
||||||
if err := xml.Unmarshal(v.Query, &iqErrorCancelNotAcceptable); err == nil {
|
if err := xml.Unmarshal(v.Query, &iqErrorCancelNotAcceptable); err == nil {
|
||||||
if v.To == talk.JID() {
|
if v.To == j.Talk.JID() {
|
||||||
nick := strings.SplitN(v.From, "/", 2)[1]
|
nick := strings.SplitN(v.From, "/", 2)[1]
|
||||||
room := strings.SplitN(v.From, "/", 2)[0]
|
room := strings.SplitN(v.From, "/", 2)[0]
|
||||||
|
|
||||||
if slices.Contains(roomsConnected, iqErrorCancelNotAcceptable.By) &&
|
if slices.Contains(j.RoomsConnected, iqErrorCancelNotAcceptable.By) &&
|
||||||
nick == getBotNickFromRoomConfig(room) {
|
nick == j.GetBotNickFromRoomConfig(room) {
|
||||||
|
|
||||||
log.Errorf(
|
log.Errorf(
|
||||||
"Got Iq error message from: %s to: %s. Looks like i'm not in MUC anymore",
|
"Got Iq error message from: %s to: %s. Looks like i'm not in MUC anymore",
|
||||||
v.From, v.To,
|
v.From, v.To,
|
||||||
)
|
)
|
||||||
|
|
||||||
time.Sleep(time.Duration(config.Jabber.MucRejoinDelay) * time.Second)
|
time.Sleep(time.Duration(j.C.Jabber.MucRejoinDelay) * time.Second)
|
||||||
|
|
||||||
if _, err := talk.JoinMUCNoHistory(iqErrorCancelNotAcceptable.By, nick); err != nil {
|
if _, err := j.Talk.JoinMUCNoHistory(iqErrorCancelNotAcceptable.By, nick); err != nil {
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
"looks like connection to server also lost err=%w",
|
"looks like connection to server also lost err=%w",
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -546,8 +546,8 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
// Смена статуса участника
|
// Смена статуса участника
|
||||||
case xmpp.Presence:
|
case xmpp.Presence:
|
||||||
if muc, _ := strings.CutSuffix(v.To, "/"); muc != "" {
|
if muc, _ := strings.CutSuffix(v.To, "/"); muc != "" {
|
||||||
if slices.Contains(roomsConnected, muc) {
|
if slices.Contains(j.RoomsConnected, muc) {
|
||||||
lastMucActivity.Set(muc, lastServerActivity)
|
j.LastMucActivity.Set(muc, j.LastServerActivity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,12 +559,12 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
// Однако, это не значит, что такую ситуацию мы не должны корректным образом обрабатывать.
|
// Однако, это не значит, что такую ситуацию мы не должны корректным образом обрабатывать.
|
||||||
if v.Type == "unavailable" {
|
if v.Type == "unavailable" {
|
||||||
// Считаем, что мы больше не в комнате, поэтому не знаем, кто там есть
|
// Считаем, что мы больше не в комнате, поэтому не знаем, кто там есть
|
||||||
roomPresences.Delete(v.From)
|
j.RoomPresences.Delete(v.From)
|
||||||
|
|
||||||
log.Error("Presence notification - looks like another instance of client leaves room")
|
log.Error("Presence notification - looks like another instance of client leaves room")
|
||||||
|
|
||||||
if slices.Contains(roomsConnected, v.From) {
|
if slices.Contains(j.RoomsConnected, v.From) {
|
||||||
go joinMuc(v.From)
|
go j.JoinMuc(v.From)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Errorf("Presence notification, Type: %s, From: %s, Show: %s, Status: %s",
|
log.Errorf("Presence notification, Type: %s, From: %s, Show: %s, Status: %s",
|
||||||
@@ -588,19 +588,19 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
|
|
||||||
// Это наш собственный Presence
|
// Это наш собственный Presence
|
||||||
if v.Show == "" && v.Status == "" {
|
if v.Show == "" && v.Status == "" {
|
||||||
if nick == getBotNickFromRoomConfig(room) {
|
if nick == j.GetBotNickFromRoomConfig(room) {
|
||||||
roomsConnected = append(roomsConnected, room)
|
j.RoomsConnected = append(j.RoomsConnected, room)
|
||||||
// На всякий случай дедуплицируем список комнат, к которым мы заджойнились.
|
// На всякий случай дедуплицируем список комнат, к которым мы заджойнились.
|
||||||
sort.Strings(roomsConnected)
|
sort.Strings(j.RoomsConnected)
|
||||||
slices.Compact(roomsConnected)
|
slices.Compact(j.RoomsConnected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch v.Role {
|
switch v.Role {
|
||||||
// Участник ушёл
|
// Участник ушёл
|
||||||
case "none":
|
case "none":
|
||||||
if presenceJSONInterface, present := roomPresences.Get(room); present {
|
if presenceJSONInterface, present := j.RoomPresences.Get(room); present {
|
||||||
presenceJSONStrings := interfaceToStringSlice(presenceJSONInterface)
|
presenceJSONStrings := InterfaceToStringSlice(presenceJSONInterface)
|
||||||
|
|
||||||
var newPresenceJSONStrings []string
|
var newPresenceJSONStrings []string
|
||||||
|
|
||||||
@@ -615,7 +615,7 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
newPresenceJSONStrings = append(newPresenceJSONStrings, presenceJSONstring)
|
newPresenceJSONStrings = append(newPresenceJSONStrings, presenceJSONstring)
|
||||||
}
|
}
|
||||||
|
|
||||||
roomPresences.Set(room, newPresenceJSONStrings)
|
j.RoomPresences.Set(room, newPresenceJSONStrings)
|
||||||
}
|
}
|
||||||
// Участник пришёл
|
// Участник пришёл
|
||||||
default:
|
default:
|
||||||
@@ -625,8 +625,8 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
presenceJSONBytes []byte
|
presenceJSONBytes []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
if presenceJSONInterface, present := roomPresences.Get(room); present {
|
if presenceJSONInterface, present := j.RoomPresences.Get(room); present {
|
||||||
presenceJSONStrings = interfaceToStringSlice(presenceJSONInterface)
|
presenceJSONStrings = InterfaceToStringSlice(presenceJSONInterface)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, presenceJSONString := range presenceJSONStrings {
|
for _, presenceJSONString := range presenceJSONStrings {
|
||||||
@@ -644,16 +644,16 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
|
|
||||||
presenceJSONBytes, _ = json.Marshal(v) //nolint:errchkjson
|
presenceJSONBytes, _ = json.Marshal(v) //nolint:errchkjson
|
||||||
newPresenceJSONStrings = append(newPresenceJSONStrings, string(presenceJSONBytes))
|
newPresenceJSONStrings = append(newPresenceJSONStrings, string(presenceJSONBytes))
|
||||||
roomPresences.Set(room, newPresenceJSONStrings)
|
j.RoomPresences.Set(room, newPresenceJSONStrings)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем, а не злодей ли зашёл? Сделать это мы можем, только если мы находимся в комнате.
|
// Проверяем, а не злодей ли зашёл? Сделать это мы можем, только если мы находимся в комнате.
|
||||||
// По правилам, мы можем что-то делать, только после того, как нам прилетит наш собственный presence, это
|
// По правилам, мы можем что-то делать, только после того, как нам прилетит наш собственный presence, это
|
||||||
// значит, что мы вошли в комнату.
|
// значит, что мы вошли в комнату.
|
||||||
if slices.Contains(roomsConnected, room) {
|
if slices.Contains(j.RoomsConnected, room) {
|
||||||
if v.Affiliation != "outcast" {
|
if v.Affiliation != "outcast" {
|
||||||
if err := bunyPresense(v); err != nil {
|
if err := j.BunyPresense(v); err != nil {
|
||||||
gTomb.Kill(err)
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -664,8 +664,8 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
// Ответ на запрос поддерживаемых фич, который "http://jabber.org/protocol/disco#info"
|
// Ответ на запрос поддерживаемых фич, который "http://jabber.org/protocol/disco#info"
|
||||||
case xmpp.DiscoResult:
|
case xmpp.DiscoResult:
|
||||||
if muc, _ := strings.CutSuffix(v.To, "/"); muc != "" {
|
if muc, _ := strings.CutSuffix(v.To, "/"); muc != "" {
|
||||||
if slices.Contains(roomsConnected, muc) {
|
if slices.Contains(j.RoomsConnected, muc) {
|
||||||
lastMucActivity.Set(muc, lastServerActivity)
|
j.LastMucActivity.Set(muc, j.LastServerActivity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,10 +677,10 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
// Конкретно сейчас нас интересует только поддержка c2s ping
|
// Конкретно сейчас нас интересует только поддержка c2s ping
|
||||||
for _, feature := range v.Features {
|
for _, feature := range v.Features {
|
||||||
log.Debugf("Server %s announced that it supports feature: %s", v.From, feature)
|
log.Debugf("Server %s announced that it supports feature: %s", v.From, feature)
|
||||||
serverCapsList.Set(feature, true)
|
j.ServerCapsList.Set(feature, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
serverCapsQueried = true
|
j.ServerCapsQueried = true
|
||||||
|
|
||||||
case "conference":
|
case "conference":
|
||||||
mucCaps := make(map[string]bool)
|
mucCaps := make(map[string]bool)
|
||||||
@@ -690,7 +690,7 @@ func parseEvent(e interface{}) { //nolint:maintidx,gocognit,gocyclo
|
|||||||
mucCaps[feature] = true //nolint:wsl
|
mucCaps[feature] = true //nolint:wsl
|
||||||
}
|
}
|
||||||
|
|
||||||
mucCapsList.Set(v.From, mucCaps)
|
j.MucCapsList.Set(v.From, mucCaps)
|
||||||
|
|
||||||
case "pubsub":
|
case "pubsub":
|
||||||
log.Debugf("PubSub component %s reply to disco#info, skipping", v.From)
|
log.Debugf("PubSub component %s reply to disco#info, skipping", v.From)
|
||||||
77
internal/jabber/main_loop.go
Normal file
77
internal/jabber/main_loop.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package jabber
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MyLoop - основной цикл программы.
|
||||||
|
func (j *Jabber) MyLoop() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-j.GTomb.Dying():
|
||||||
|
j.GTomb.Done()
|
||||||
|
return //nolint:nlreturn
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Зададим начальное значение глобальным переменным
|
||||||
|
j.ServerPingTimestampRx = 0
|
||||||
|
j.ServerPingTimestampTx = 0
|
||||||
|
j.RoomsConnected = make([]string, 1)
|
||||||
|
j.LastActivity = 0
|
||||||
|
j.LastServerActivity = 0
|
||||||
|
j.LastMucActivity = NewCollection()
|
||||||
|
j.ServerCapsQueried = false
|
||||||
|
j.ServerCapsList = NewCollection()
|
||||||
|
j.MucCapsList = NewCollection()
|
||||||
|
j.ServerPingTimestampTx = 0
|
||||||
|
j.ServerPingTimestampRx = 0
|
||||||
|
j.RoomPresences = NewCollection()
|
||||||
|
|
||||||
|
// Установим коннект
|
||||||
|
j.EstablishConnection()
|
||||||
|
|
||||||
|
j.ServerPingTimestampRx = time.Now().Unix() // Считаем, что если коннект запустился, то первый пинг успешен.
|
||||||
|
|
||||||
|
// Тыкаем сервер палочкой, проверяем, что коннект жив и вываливаемся из mainLoop, если он не жив.
|
||||||
|
go j.ProbeServerLiveness()
|
||||||
|
|
||||||
|
// Тыкаем muc-и палочкой, проверяем, что они живы и вываливаемся из mainLoop, если пинги пропали.
|
||||||
|
// Если пинги до комнаты пропали, то это фактически значит, что либо сервер потерял связь с MUC-компонентом,
|
||||||
|
// либо у нас какой-то wire error.
|
||||||
|
go j.ProbeMUCLiveness()
|
||||||
|
|
||||||
|
// Гребём ивенты...
|
||||||
|
for {
|
||||||
|
// Стриггерилось завершение работы приложения, или соединение не установлено (порвалось, например)
|
||||||
|
// грести не надо
|
||||||
|
if j.Shutdown {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if !j.IsConnected {
|
||||||
|
// Tight loop - это наверно не очень хорошо, думаю, ничего страшного не будет, если мы поспим 100мс.
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Вынимаем ивент из "провода"
|
||||||
|
chat, err := j.Talk.Recv()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Unable to get events from server: %s", err)
|
||||||
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
|
// Не забываем выходить на ошибке :(
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
j.ParseEvent(chat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||||
@@ -1,10 +1,22 @@
|
|||||||
package main
|
package jabber
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Переменные для простенького нормализатора текста.
|
||||||
|
var (
|
||||||
|
// Знаки препинания раз.
|
||||||
|
pMarks = []string{".", ",", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "{", "}", "<", ">", "[", "]", "\\"}
|
||||||
|
|
||||||
|
// Знаки препинания два-с.
|
||||||
|
pMarks2 = []string{"-", "_", "+", "=", ":", ";", "'", "`", "~", "\""}
|
||||||
|
|
||||||
|
// Символы новой строки.
|
||||||
|
newLines = []string{"\n", "\r", "\n\r", "\r\n"}
|
||||||
|
)
|
||||||
|
|
||||||
// Нормализует текстовый буфер. Убирает начальные и конечные пробельные символы, заменяет сносы строк пробелами, удаляет
|
// Нормализует текстовый буфер. Убирает начальные и конечные пробельные символы, заменяет сносы строк пробелами, удаляет
|
||||||
// знаки препинания, схлопывает повторяющиеся пробелы в один символ.
|
// знаки препинания, схлопывает повторяющиеся пробелы в один символ.
|
||||||
func nString(buf string) string {
|
func nString(buf string) string {
|
||||||
@@ -40,3 +52,5 @@ func nStringLower(buf string) string {
|
|||||||
func nStringUpper(buf string) string {
|
func nStringUpper(buf string) string {
|
||||||
return strings.ToUpper(nString(buf))
|
return strings.ToUpper(nString(buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package jabber
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -11,9 +11,9 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// readConfig читает и валидирует конфиг, а также выставляет некоторые default-ы, если значений для параметров в конфиге
|
// ReadConfig читает и валидирует конфиг, а также выставляет некоторые default-ы, если значений для параметров в конфиге
|
||||||
// нет.
|
// нет.
|
||||||
func readConfig() error { //nolint:gocognit,gocyclo
|
func (j *Jabber) ReadConfig() error { //nolint:gocognit,gocyclo
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
executablePath string
|
executablePath string
|
||||||
@@ -31,9 +31,9 @@ func readConfig() error { //nolint:gocognit,gocyclo
|
|||||||
configJSONPath := fmt.Sprintf("%s/data/config.json", filepath.Dir(executablePath))
|
configJSONPath := fmt.Sprintf("%s/data/config.json", filepath.Dir(executablePath))
|
||||||
|
|
||||||
locations := []string{
|
locations := []string{
|
||||||
"~/.bunyPresense-jabber-bot.json",
|
"~/.buny-jabber-bot.json",
|
||||||
"~/bunyPresense-jabber-bot.json",
|
"~/buny-jabber-bot.json",
|
||||||
"/etc/bunyPresense-jabber-bot.json",
|
"/etc/buny-jabber-bot.json",
|
||||||
configJSONPath,
|
configJSONPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ func readConfig() error { //nolint:gocognit,gocyclo
|
|||||||
// Интереснее на выходе получить структурку: то есть мы вначале конфиг преобразуем в map-ку, затем эту map-ку
|
// Интереснее на выходе получить структурку: то есть мы вначале конфиг преобразуем в map-ку, затем эту map-ку
|
||||||
// сериализуем в json, а потом json превращаем в структурку. Не очень эффективно, но он и нечасто требуется.
|
// сериализуем в json, а потом json превращаем в структурку. Не очень эффективно, но он и нечасто требуется.
|
||||||
var (
|
var (
|
||||||
sampleConfig myConfig
|
sampleConfig MyConfig
|
||||||
tmp map[string]interface{}
|
tmp map[string]interface{}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ func readConfig() error { //nolint:gocognit,gocyclo
|
|||||||
|
|
||||||
// sampleConfig.Log = "" if not set
|
// sampleConfig.Log = "" if not set
|
||||||
|
|
||||||
config = sampleConfig
|
j.C = sampleConfig
|
||||||
configLoaded = true
|
configLoaded = true
|
||||||
|
|
||||||
log.Infof("Using %s as config file", location)
|
log.Infof("Using %s as config file", location)
|
||||||
@@ -276,3 +276,5 @@ func readConfig() error { //nolint:gocognit,gocyclo
|
|||||||
|
|
||||||
return err //nolint:wrapcheck
|
return err //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||||
58
internal/jabber/sig_handler.go
Normal file
58
internal/jabber/sig_handler.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package jabber
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/eleksir/go-xmpp"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (j *Jabber) SigHandler() {
|
||||||
|
log.Debug("Installing signal handler")
|
||||||
|
|
||||||
|
for s := range j.SigChan {
|
||||||
|
switch s {
|
||||||
|
case syscall.SIGINT:
|
||||||
|
log.Infoln("Got SIGINT, quitting")
|
||||||
|
case syscall.SIGTERM:
|
||||||
|
log.Infoln("Got SIGTERM, quitting")
|
||||||
|
case syscall.SIGQUIT:
|
||||||
|
log.Infoln("Got SIGQUIT, quitting")
|
||||||
|
|
||||||
|
// Заходим на новую итерацию, если у нас "неинтересный" сигнал.
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Чтобы не срать в логи ошибками, проставим shutdown state приложения в true.
|
||||||
|
j.Shutdown = true
|
||||||
|
|
||||||
|
if j.IsConnected && !j.Shutdown {
|
||||||
|
log.Debug("Try to set our presence to Unavailable and status to Offline")
|
||||||
|
|
||||||
|
// Вот тут понадобится коллекция известных пользователей, чтобы им разослать presence, что бот свалил в
|
||||||
|
// offline. Пока за неимением лучшего сообщим об этом самим себе.
|
||||||
|
for _, room := range j.RoomsConnected {
|
||||||
|
if _, err := j.Talk.SendPresence(
|
||||||
|
xmpp.Presence{ //nolint:exhaustruct
|
||||||
|
To: room,
|
||||||
|
Status: "Offline",
|
||||||
|
Type: "unavailable",
|
||||||
|
},
|
||||||
|
); err != nil {
|
||||||
|
log.Infof("Unable to send presence to jabber server: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// И закрываем соединение.
|
||||||
|
log.Infoln("Closing connection to jabber server")
|
||||||
|
|
||||||
|
if err := j.Talk.Close(); err != nil {
|
||||||
|
log.Infof("Unable to close connection to jabber server: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
78
internal/jabber/squash.go
Normal file
78
internal/jabber/squash.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package jabber
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/eleksir/go-xmpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Squash банит указанный jid в указанной комнате.
|
||||||
|
// reasonEnable указывает, надо ли писать дату автобана в банлисте в поле reason (это единственная причина, в которую
|
||||||
|
// умеет бот).
|
||||||
|
func (j *Jabber) Squash(room, jid string, reasonEnable bool, vType string) (string, error) {
|
||||||
|
var (
|
||||||
|
id string
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if j.C.Jabber.BanPhrasesEnable {
|
||||||
|
phrase := RandomPhrase(j.C.Jabber.BanPhrases)
|
||||||
|
|
||||||
|
if _, err = j.Talk.Send(
|
||||||
|
xmpp.Chat{ //nolint:exhaustruct
|
||||||
|
Remote: room,
|
||||||
|
Text: phrase,
|
||||||
|
Type: vType,
|
||||||
|
},
|
||||||
|
); err != nil {
|
||||||
|
err = fmt.Errorf("unable to send phrase to room %s: %w", room, err)
|
||||||
|
|
||||||
|
// Здесь возвращаем nil, т.к. за нас ошибку залоггирует код выше.
|
||||||
|
return id, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://xmpp.org/extensions/xep-0045.html#ban баним вот таким сообщением
|
||||||
|
ban := "<item affiliation='outcast' jid='" + jid + "'>"
|
||||||
|
|
||||||
|
if reasonEnable {
|
||||||
|
var t = time.Now()
|
||||||
|
ban += fmt.Sprintf(
|
||||||
|
"<reason>autoban at %04d.%02d.%02d %02d:%02d:%02d</reason>",
|
||||||
|
t.Year(),
|
||||||
|
t.Month(),
|
||||||
|
t.Day(),
|
||||||
|
t.Hour(),
|
||||||
|
t.Minute(),
|
||||||
|
t.Second(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
ban += "<reason />"
|
||||||
|
}
|
||||||
|
|
||||||
|
ban += "</item>"
|
||||||
|
|
||||||
|
// Выжидаем некоторое время перед баном. А то можно настолько рано забанить, что сервер не внесёт злодея в банлист
|
||||||
|
// комнаты и пришлёт affiliation: none вместо affiliation: outcast.
|
||||||
|
if j.C.Jabber.BanDelay > 0 {
|
||||||
|
time.Sleep(time.Duration(j.C.Jabber.BanDelay) * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
if id, err = j.Talk.RawInformationQuery(
|
||||||
|
j.Talk.JID(),
|
||||||
|
room,
|
||||||
|
"ban1",
|
||||||
|
xmpp.IQTypeSet,
|
||||||
|
"http://jabber.org/protocol/muc#admin",
|
||||||
|
ban,
|
||||||
|
); err != nil {
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"unable to ban user: id=%s, err=%w",
|
||||||
|
id,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return id, err
|
||||||
|
}
|
||||||
@@ -1,11 +1,15 @@
|
|||||||
package main
|
package jabber
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/eleksir/go-xmpp"
|
||||||
|
"gopkg.in/tomb.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// myConfig прототип структурки с конфигом.
|
// MyConfig прототип структурки с конфигом.
|
||||||
type myConfig struct {
|
type MyConfig struct {
|
||||||
Jabber struct {
|
Jabber struct {
|
||||||
Server string `json:"server,omitempty"`
|
Server string `json:"server,omitempty"`
|
||||||
Port int `json:"port,omitempty"`
|
Port int `json:"port,omitempty"`
|
||||||
@@ -56,8 +60,8 @@ type myConfig struct {
|
|||||||
Log string `json:"log,omitempty"`
|
Log string `json:"log,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// myWhiteList прототип структурки с белым списком jid-ов.
|
// MyWhiteList прототип структурки с белым списком jid-ов.
|
||||||
type myWhiteList struct {
|
type MyWhiteList struct {
|
||||||
Whitelist []struct {
|
Whitelist []struct {
|
||||||
RoomName string `json:"room_name,omitempty"`
|
RoomName string `json:"room_name,omitempty"`
|
||||||
Jid []string `json:"jid,omitempty"`
|
Jid []string `json:"jid,omitempty"`
|
||||||
@@ -65,8 +69,8 @@ type myWhiteList struct {
|
|||||||
} `json:"whitelist,omitempty"`
|
} `json:"whitelist,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// myBlackList прототип структурки с чёрным списком jid-ов.
|
// MyBlackList прототип структурки с чёрным списком jid-ов.
|
||||||
type myBlackList struct {
|
type MyBlackList struct {
|
||||||
Blacklist []struct {
|
Blacklist []struct {
|
||||||
RoomName string `json:"room_name,omitempty"`
|
RoomName string `json:"room_name,omitempty"`
|
||||||
ReasonEnable bool `json:"reason_enable,omitempty"`
|
ReasonEnable bool `json:"reason_enable,omitempty"`
|
||||||
@@ -76,17 +80,82 @@ type myBlackList struct {
|
|||||||
} `json:"blacklist,omitempty"`
|
} `json:"blacklist,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// jabberSimpleIqGetQuery прототип структурки для разбора запросов xmpp discovery query, например,
|
// Jabber основная структура-объект, содержащая стейты и проч.
|
||||||
|
type Jabber struct {
|
||||||
|
// C - конфиг, как он распарсился из конфиг-файла.
|
||||||
|
C MyConfig
|
||||||
|
|
||||||
|
// WhiteList - структурка с безусловно разрешёнными jid-ами
|
||||||
|
WhiteList MyWhiteList
|
||||||
|
|
||||||
|
// BlackList - структурка с запрещёнными по регуляркам фразами, никами, jid-ами.
|
||||||
|
BlackList MyBlackList
|
||||||
|
|
||||||
|
// Опции подключения к xmpp-серверу.
|
||||||
|
Options *xmpp.Options
|
||||||
|
|
||||||
|
// gTomb пул активных горутин.
|
||||||
|
GTomb tomb.Tomb
|
||||||
|
|
||||||
|
// Talk основная структурка xmpp-клиента.
|
||||||
|
Talk *xmpp.Client
|
||||||
|
|
||||||
|
// sync.Map-ка с капабилити сервера.
|
||||||
|
ServerCapsList *Collection
|
||||||
|
|
||||||
|
// ServerCapsQueried показывает, были ли запрошены capabilities сервера.
|
||||||
|
ServerCapsQueried bool
|
||||||
|
|
||||||
|
// Время последней активности, нужно для c2s пингов - посылаем пинги, только если давненько ничего не приходило с
|
||||||
|
// сервера.
|
||||||
|
LastServerActivity int64
|
||||||
|
|
||||||
|
// Время, когда был отправлен c2s ping.
|
||||||
|
ServerPingTimestampTx int64
|
||||||
|
|
||||||
|
// Время, когда был принят s2c pong.
|
||||||
|
ServerPingTimestampRx int64
|
||||||
|
|
||||||
|
// Время последней активности, нужно для jabber:iq:last.
|
||||||
|
LastActivity int64
|
||||||
|
|
||||||
|
// sync.Map-ка с комнатами и их capability.
|
||||||
|
MucCapsList *Collection
|
||||||
|
|
||||||
|
// Время последней активности MUC-ов, нужно для пингов - посылаем пинги, только если давненько ничего не приходило из
|
||||||
|
// muc-ов.
|
||||||
|
LastMucActivity *Collection
|
||||||
|
|
||||||
|
// Список комнат, в которых находится бот.
|
||||||
|
RoomsConnected []string
|
||||||
|
|
||||||
|
// sync.Map-ка со списком участников конференций (в json-формате, согласно структуре xmpp.Presence, "room".[]json).
|
||||||
|
RoomPresences *Collection
|
||||||
|
|
||||||
|
// Канал, по котором приходят сообщения о том, что ОС отправила некие сигналы процессу.
|
||||||
|
SigChan chan os.Signal
|
||||||
|
|
||||||
|
// Индиктор того, что процесс завершается.
|
||||||
|
Shutdown bool
|
||||||
|
|
||||||
|
// Индиктор того, что соединение установлено.
|
||||||
|
IsConnected bool
|
||||||
|
|
||||||
|
// Индикатор того, что соединение в процессе достукивания до сервера.
|
||||||
|
Connecting bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// JabberSimpleIqGetQuery прототип структурки для разбора запросов xmpp discovery query, например,
|
||||||
// https://xmpp.org/extensions/xep-0030.html#example-18 .
|
// https://xmpp.org/extensions/xep-0030.html#example-18 .
|
||||||
type jabberSimpleIqGetQuery struct {
|
type JabberSimpleIqGetQuery struct {
|
||||||
XMLName xml.Name `xml:"query"`
|
XMLName xml.Name `xml:"query"`
|
||||||
Text string `xml:",chardata"`
|
Text string `xml:",chardata"`
|
||||||
Xmlns string `xml:"xmlns,attr"`
|
Xmlns string `xml:"xmlns,attr"`
|
||||||
Node string `xml:"node,attr,omitempty"` // для xmlns="http://jabber.org/protocol/disco#items"
|
Node string `xml:"node,attr,omitempty"` // для xmlns="http://jabber.org/protocol/disco#items"
|
||||||
}
|
}
|
||||||
|
|
||||||
// jabberPubsubIQGetQuery прототип структурки для разбора запросов xmpp pubsub.
|
// JabberPubsubIQGetQuery прототип структурки для разбора запросов xmpp pubsub.
|
||||||
type jabberPubsubIQGetQuery struct {
|
type JabberPubsubIQGetQuery struct {
|
||||||
XMLName xml.Name `xml:"pubsub"`
|
XMLName xml.Name `xml:"pubsub"`
|
||||||
Text string `xml:",chardata"`
|
Text string `xml:",chardata"`
|
||||||
Xmlns string `xml:"xmlns,attr"`
|
Xmlns string `xml:"xmlns,attr"`
|
||||||
@@ -97,25 +166,25 @@ type jabberPubsubIQGetQuery struct {
|
|||||||
} `xml:"items"`
|
} `xml:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// jabberTimeIqGetQuery прототип структурки для разбора IQ запросов на локальное время клиента,
|
// JabberTimeIqGetQuery прототип структурки для разбора IQ запросов на локальное время клиента,
|
||||||
// https://xmpp.org/extensions/xep-0202.html
|
// https://xmpp.org/extensions/xep-0202.html
|
||||||
type jabberTimeIqGetQuery struct {
|
type JabberTimeIqGetQuery struct {
|
||||||
// <time xmlns="urn:xmpp:time"/>
|
// <time xmlns="urn:xmpp:time"/>
|
||||||
XMLName xml.Name `xml:"time"`
|
XMLName xml.Name `xml:"time"`
|
||||||
Text string `xml:",chardata"`
|
Text string `xml:",chardata"`
|
||||||
Xmlns string `xml:"xmlns,attr"`
|
Xmlns string `xml:"xmlns,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// jabberIqPing прототип структурки для разбора IQ запросов на пинг клиента, https://xmpp.org/extensions/xep-0199.html
|
// JabberIqPing прототип структурки для разбора IQ запросов на пинг клиента, https://xmpp.org/extensions/xep-0199.html
|
||||||
type jabberIqPing struct {
|
type JabberIqPing struct {
|
||||||
XMLName xml.Name `xml:"ping"`
|
XMLName xml.Name `xml:"ping"`
|
||||||
Text string `xml:",chardata"`
|
Text string `xml:",chardata"`
|
||||||
Xmlns string `xml:"xmlns,attr"`
|
Xmlns string `xml:"xmlns,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// jabberIqErrorCancelNotAcceptable прототип структурки для разбора IQ ответов, когда сервис (сервер, клиент, etc) не
|
// JabberIqErrorCancelNotAcceptable прототип структурки для разбора IQ ответов, когда сервис (сервер, клиент, etc) не
|
||||||
// может или не хочет принимать наш iq-запрос https://xmpp.org/extensions/xep-0099.html
|
// может или не хочет принимать наш iq-запрос https://xmpp.org/extensions/xep-0099.html
|
||||||
type jabberIqErrorCancelNotAcceptable struct {
|
type JabberIqErrorCancelNotAcceptable struct {
|
||||||
XMLName xml.Name `xml:"error"`
|
XMLName xml.Name `xml:"error"`
|
||||||
Text string `xml:",chardata"`
|
Text string `xml:",chardata"`
|
||||||
Type string `xml:"type,attr"`
|
Type string `xml:"type,attr"`
|
||||||
467
internal/jabber/util.go
Normal file
467
internal/jabber/util.go
Normal file
@@ -0,0 +1,467 @@
|
|||||||
|
package jabber
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"reflect"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/eleksir/go-xmpp"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RandomPhrase выдаёт одну рандомную фразу из даденного списка фраз.
|
||||||
|
func RandomPhrase(list []string) string {
|
||||||
|
phrase := ""
|
||||||
|
|
||||||
|
if listLen := len(list); listLen > 0 {
|
||||||
|
phrase = list[rand.Intn(listLen)]
|
||||||
|
}
|
||||||
|
|
||||||
|
return phrase
|
||||||
|
}
|
||||||
|
|
||||||
|
// InterfaceToStringSlice превращает данный интерфейс в слайс строк.
|
||||||
|
// Если может, конечно :) .
|
||||||
|
func InterfaceToStringSlice(iface interface{}) []string {
|
||||||
|
var mySlice []string
|
||||||
|
|
||||||
|
// А теперь мы начинаем дурдом, нам надо превратить ёбанный interface{} в []string
|
||||||
|
// Поскольку interface{} может быть чем угодно, перестрахуемся
|
||||||
|
if reflect.TypeOf(iface).Kind() == reflect.Slice {
|
||||||
|
shit := reflect.ValueOf(iface)
|
||||||
|
|
||||||
|
for i := 0; i < shit.Len(); i++ {
|
||||||
|
mySlice = append(mySlice, fmt.Sprint(shit.Index(i)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mySlice
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRealJIDfromNick достаёт из запомненных presence-ов по даденному nick-у real jid с resource-ом. Nick должен
|
||||||
|
// содержать имя конфы, откуда участник.
|
||||||
|
func (j *Jabber) GetRealJIDfromNick(fullNick string) string {
|
||||||
|
var p xmpp.Presence
|
||||||
|
|
||||||
|
room := (strings.SplitN(fullNick, "/", 2))[0]
|
||||||
|
|
||||||
|
// Достанем presence участника
|
||||||
|
presenceJSONInterface, present := j.RoomPresences.Get(room)
|
||||||
|
|
||||||
|
// Никого нет дома
|
||||||
|
if !present {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
presenceJSONStrings := InterfaceToStringSlice(presenceJSONInterface)
|
||||||
|
|
||||||
|
for _, presepresenceJSONString := range presenceJSONStrings {
|
||||||
|
_ = json.Unmarshal([]byte(presepresenceJSONString), &p)
|
||||||
|
|
||||||
|
if p.From == fullNick {
|
||||||
|
return p.JID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBotNickFromRoomConfig достаёт из настроек комнаты короткий ник бота, либо берёт значение из конфига, если ник в
|
||||||
|
// настройках комнаты не задан. Короткий ник не содержит название комнаты.
|
||||||
|
func (j *Jabber) GetBotNickFromRoomConfig(room string) string {
|
||||||
|
for _, roomStruct := range j.C.Jabber.Channels {
|
||||||
|
if roomStruct.Name == room {
|
||||||
|
return roomStruct.Nick
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return j.C.Jabber.Nick
|
||||||
|
}
|
||||||
|
|
||||||
|
// RotateStatus периодически изменяет статус бота в MUC-е согласно настройкам из кофига.
|
||||||
|
func (j *Jabber) RotateStatus(room string) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-j.GTomb.Dying():
|
||||||
|
j.GTomb.Done()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
default:
|
||||||
|
// TODO: Переделать на ticker-ы
|
||||||
|
totalSleepTime := time.Duration(j.C.Jabber.RuntimeStatus.RotationTime) * time.Second
|
||||||
|
totalSleepTime += time.Duration(j.C.Jabber.RuntimeStatus.RotationSplayTime) * time.Second
|
||||||
|
|
||||||
|
for {
|
||||||
|
status := RandomPhrase(j.C.Jabber.RuntimeStatus.Text)
|
||||||
|
log.Debugf("Set status for MUC: %s to: %s", room, status)
|
||||||
|
|
||||||
|
var p xmpp.Presence
|
||||||
|
|
||||||
|
if room != "" {
|
||||||
|
p = xmpp.Presence{ //nolint:exhaustruct
|
||||||
|
To: room,
|
||||||
|
Status: status,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p = xmpp.Presence{ //nolint:exhaustruct
|
||||||
|
Status: status,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := j.Talk.SendPresence(p); err != nil {
|
||||||
|
log.Infof("Unable to send presence to MUC %s: %s", room, err)
|
||||||
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если мы не хотим ротировать, то цикл нам тут не нужен, просто выходим.
|
||||||
|
if j.C.Jabber.RuntimeStatus.RotationTime == 0 {
|
||||||
|
j.GTomb.Done()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(totalSleepTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// JoinMuc джойнится к конференциям/каналам/комнатам в джаббере.
|
||||||
|
func (j *Jabber) JoinMuc(room string) {
|
||||||
|
log.Debugf("Sending disco#info from %s to %s", j.Talk.JID(), room)
|
||||||
|
|
||||||
|
if _, err := j.Talk.DiscoverInfo(j.Talk.JID(), room); err != nil {
|
||||||
|
log.Infof("Unable to send disco#info to MUC %s: %s", room, err)
|
||||||
|
|
||||||
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ждём, пока muc нам вернёт список фичей.
|
||||||
|
for i := 0; i < (20 * int(j.C.Jabber.ConnectionTimeout)); i++ {
|
||||||
|
var (
|
||||||
|
myRoom interface{}
|
||||||
|
supported bool
|
||||||
|
exist bool
|
||||||
|
)
|
||||||
|
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
|
||||||
|
if myRoom, exist = j.MucCapsList.Get(room); !exist {
|
||||||
|
// Пока не задискаверилась.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if supported, exist = myRoom.(map[string]bool)["muc_unsecured"]; exist {
|
||||||
|
if supported {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Unable to join to password-protected room. Don't know how to enter passwords :)")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Заходим в конфу, наконец-то
|
||||||
|
if _, err := j.Talk.JoinMUCNoHistory(room, j.GetBotNickFromRoomConfig(room)); err != nil {
|
||||||
|
log.Errorf("Unable to join to MUC: %s", room)
|
||||||
|
|
||||||
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Joining to MUC: %s", room)
|
||||||
|
|
||||||
|
// Ждём, когда прилетит presence из комнаты, тогда мы точно знаем, что мы вошли.
|
||||||
|
entered := false
|
||||||
|
|
||||||
|
for i := 0; i < (20 * int(j.C.Jabber.ConnectionTimeout)); i++ {
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
|
||||||
|
if slices.Contains(j.RoomsConnected, room) {
|
||||||
|
entered = true
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !entered {
|
||||||
|
log.Errorf(
|
||||||
|
"Unable to enter to MUC %s, join timeout after %d seconds (server does not return my presence for this room)",
|
||||||
|
room,
|
||||||
|
20*int(j.C.Jabber.ConnectionTimeout)+1,
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Вот теперь точно можно слать статус.
|
||||||
|
log.Infof("Joined to MUC: %s", room)
|
||||||
|
|
||||||
|
go j.RotateStatus(room)
|
||||||
|
|
||||||
|
// Время проверить участников на предмет злобности
|
||||||
|
namesInterface, present := j.RoomPresences.Get(room)
|
||||||
|
|
||||||
|
// Если room есть в списке presence-ов, то фигачим. room там должен быть, просто обязан.
|
||||||
|
if present {
|
||||||
|
for _, name := range InterfaceToStringSlice(namesInterface) {
|
||||||
|
var v xmpp.Presence
|
||||||
|
|
||||||
|
_ = json.Unmarshal([]byte(name), &v)
|
||||||
|
log.Infof("Fake presence forged for %s just for on-enter check", name)
|
||||||
|
// Оно там внутри всё само обработает, если вдруг возникнет wire error, то зарекконетится.
|
||||||
|
_ = j.BunyPresense(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EstablishConnection устанавливает соединение с jabber-сервером.
|
||||||
|
func (j *Jabber) EstablishConnection() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if j.Connecting && !j.IsConnected {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проставляем глобальные переменные.
|
||||||
|
j.Connecting = true
|
||||||
|
j.IsConnected = false
|
||||||
|
j.RoomsConnected = make([]string, 0)
|
||||||
|
|
||||||
|
log.Debugf("Establishing connection to %s", j.Options.Host)
|
||||||
|
j.Talk, err = j.Options.NewClient()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// По идее keepalive должен же проходить только, если мы уже на сервере, так?
|
||||||
|
if _, err := j.Talk.SendKeepAlive(); err != nil {
|
||||||
|
log.Errorf("Try to send initial KeepAlive, got error: %s", err)
|
||||||
|
|
||||||
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Connected")
|
||||||
|
|
||||||
|
// Джойнимся к чятикам, но делаем это в фоне, чтобы не блочиться на ошибках, например, если бота забанили
|
||||||
|
for _, roomStruct := range j.C.Jabber.Channels {
|
||||||
|
room := roomStruct.Name
|
||||||
|
go j.JoinMuc(room)
|
||||||
|
}
|
||||||
|
|
||||||
|
go j.RotateStatus("")
|
||||||
|
|
||||||
|
j.LastActivity = time.Now().Unix()
|
||||||
|
j.Connecting = false
|
||||||
|
j.IsConnected = true
|
||||||
|
|
||||||
|
log.Debugf("Sending disco#info to %s", j.C.Jabber.Server)
|
||||||
|
|
||||||
|
_, err = j.Talk.DiscoverInfo(j.Talk.JID(), j.C.Jabber.Server)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Infof("Unable to send disco#info to jabber server: %s", err)
|
||||||
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProbeServerLiveness проверяет живость соединения с сервером. Для многих серверов обязательная штука, без которой
|
||||||
|
// они выкидывают (дисконнектят) клиента через некоторое время неактивности.
|
||||||
|
func (j *Jabber) ProbeServerLiveness() { //nolint:gocognit
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-j.GTomb.Dying():
|
||||||
|
j.GTomb.Done()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
default:
|
||||||
|
for {
|
||||||
|
if j.Shutdown {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sleepTime := time.Duration(j.C.Jabber.ServerPingDelay) * 1000 * time.Millisecond
|
||||||
|
sleepTime += time.Duration(rand.Int63n(1000*j.C.Jabber.PingSplayDelay)) * time.Millisecond
|
||||||
|
time.Sleep(sleepTime)
|
||||||
|
|
||||||
|
if !j.IsConnected {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Пингуем, только если не было никакой активности в течение > config.Jabber.ServerPingDelay,
|
||||||
|
// в худшем случе это будет ~ (config.Jabber.PingSplayDelay * 2) + config.Jabber.PingSplayDelay
|
||||||
|
// if (time.Now().Unix() - lastServerActivity) < (config.Jabber.ServerPingDelay + config.Jabber.PingSplayDelay) {
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
|
||||||
|
if j.ServerCapsQueried { // Сервер ответил на disco#info
|
||||||
|
var (
|
||||||
|
value interface{}
|
||||||
|
exist bool
|
||||||
|
)
|
||||||
|
|
||||||
|
value, exist = j.ServerCapsList.Get("urn:xmpp:ping")
|
||||||
|
|
||||||
|
switch {
|
||||||
|
// Сервер анонсировал, что умеет в c2s пинги
|
||||||
|
case exist && value.(bool):
|
||||||
|
// Таймаут c2s пинга. Возьмём сумму задержки между пингами, добавим таймаут коннекта и добавим
|
||||||
|
// максимальную корректировку разброса.
|
||||||
|
txTimeout := j.C.Jabber.ServerPingDelay + j.C.Jabber.ConnectionTimeout
|
||||||
|
txTimeout += j.C.Jabber.PingSplayDelay
|
||||||
|
rxTimeout := txTimeout
|
||||||
|
|
||||||
|
rxTimeAgo := time.Now().Unix() - j.ServerPingTimestampRx
|
||||||
|
|
||||||
|
if j.ServerPingTimestampTx > 0 { // Первая пуля от нас ушла...
|
||||||
|
switch {
|
||||||
|
// Давненько мы не получали понгов от сервера, вероятно, соединение с сервером утеряно?
|
||||||
|
case rxTimeAgo > (rxTimeout * 2):
|
||||||
|
err := fmt.Errorf( //nolint:goerr113
|
||||||
|
"stall connection detected. No c2s pong for %d seconds",
|
||||||
|
rxTimeAgo,
|
||||||
|
)
|
||||||
|
|
||||||
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
// По-умолчанию, мы отправляем c2s пинг
|
||||||
|
default:
|
||||||
|
log.Debugf("Sending c2s ping from %s to %s", j.Talk.JID(), j.C.Jabber.Server)
|
||||||
|
|
||||||
|
if err := j.Talk.PingC2S(j.Talk.JID(), j.C.Jabber.Server); err != nil {
|
||||||
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
j.ServerPingTimestampTx = time.Now().Unix()
|
||||||
|
}
|
||||||
|
} else { // Первая пуля пока не вылетела, отправляем
|
||||||
|
log.Debugf("Sending first c2s ping from %s to %s", j.Talk.JID(), j.C.Jabber.Server)
|
||||||
|
|
||||||
|
if err := j.Talk.PingC2S(j.Talk.JID(), j.C.Jabber.Server); err != nil {
|
||||||
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
j.ServerPingTimestampTx = time.Now().Unix()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сервер не анонсировал, что умеет в c2s пинги
|
||||||
|
default:
|
||||||
|
log.Debug("Sending keepalive whitespace ping")
|
||||||
|
|
||||||
|
if _, err := j.Talk.SendKeepAlive(); err != nil {
|
||||||
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // Сервер не ответил на disco#info
|
||||||
|
log.Debug("Sending keepalive whitespace ping")
|
||||||
|
|
||||||
|
if _, err := j.Talk.SendKeepAlive(); err != nil {
|
||||||
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProbeMUCLiveness Пингует MUC-и, нужно для проверки, что клиент ещё находится в MUC-е.
|
||||||
|
func (j *Jabber) ProbeMUCLiveness() { //nolint:gocognit
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-j.GTomb.Dying():
|
||||||
|
j.GTomb.Done()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
default:
|
||||||
|
for {
|
||||||
|
for _, room := range j.RoomsConnected {
|
||||||
|
var (
|
||||||
|
exist bool
|
||||||
|
lastActivityTS interface{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Если записи про комнату нету, то пинговать её бессмысленно.
|
||||||
|
if lastActivityTS, exist = j.LastMucActivity.Get(room); !exist {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если время последней активности в чятике не превысило
|
||||||
|
// j.C.Jabber.ServerPingDelay + j.C.Jabber.PingSplayDelay, ничего не пингуем.
|
||||||
|
if (time.Now().Unix() - lastActivityTS.(int64)) < (j.C.Jabber.ServerPingDelay + j.C.Jabber.PingSplayDelay) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Пинг MUC-а по сценарию без серверной оптимизации мы реализовывать не будем. Это как-то не надёжно.
|
||||||
|
go func(room string) {
|
||||||
|
// Небольшая рандомная задержка перед пингом комнаты
|
||||||
|
sleepTime := time.Duration(rand.Int63n(1000*j.C.Jabber.PingSplayDelay)) * time.Millisecond //nolint:gosec
|
||||||
|
time.Sleep(sleepTime)
|
||||||
|
|
||||||
|
if err := j.Talk.PingS2S(talk.JID(), room+"/"+j.GetBotNickFromRoomConfig(room)); err != nil {
|
||||||
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}(room)
|
||||||
|
*/
|
||||||
|
var roomMap interface{}
|
||||||
|
|
||||||
|
roomMap, exist = j.MucCapsList.Get(room)
|
||||||
|
|
||||||
|
// Пинги комнаты проводим, только если она записана, как прошедшая disco#info и поддерживающая
|
||||||
|
// Server Optimization.
|
||||||
|
if exist && roomMap.(map[string]bool)["http://jabber.org/protocol/muc#self-ping-optimization"] {
|
||||||
|
go func(room string) {
|
||||||
|
// Небольшая рандомная задержка перед пингом комнаты.
|
||||||
|
sleepTime := time.Duration(rand.Int63n(1000*j.C.Jabber.PingSplayDelay)) * time.Millisecond
|
||||||
|
time.Sleep(sleepTime)
|
||||||
|
|
||||||
|
log.Debugf("Sending MUC ping from %s to %s", j.Talk.JID(), room)
|
||||||
|
|
||||||
|
if err := j.Talk.PingS2S(j.Talk.JID(), room); err != nil {
|
||||||
|
err := fmt.Errorf("unable to ping MUC %s: %w", room, err)
|
||||||
|
j.GTomb.Kill(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}(room)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Duration(j.C.Jabber.MucPingDelay) * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||||
714
lib.go
714
lib.go
@@ -1,714 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/eleksir/go-xmpp"
|
|
||||||
"github.com/hjson/hjson-go"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"golang.org/x/exp/slices"
|
|
||||||
)
|
|
||||||
|
|
||||||
// sigHandler Хэндлер сигналов закрывает все бд, все сетевые соединения и сваливает из приложения.
|
|
||||||
func sigHandler() {
|
|
||||||
log.Debug("Installing signal handler")
|
|
||||||
|
|
||||||
for s := range sigChan {
|
|
||||||
switch s {
|
|
||||||
case syscall.SIGINT:
|
|
||||||
log.Infoln("Got SIGINT, quitting")
|
|
||||||
case syscall.SIGTERM:
|
|
||||||
log.Infoln("Got SIGTERM, quitting")
|
|
||||||
case syscall.SIGQUIT:
|
|
||||||
log.Infoln("Got SIGQUIT, quitting")
|
|
||||||
|
|
||||||
// Заходим на новую итерацию, если у нас "неинтересный" сигнал.
|
|
||||||
default:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Чтобы не срать в логи ошибками, проставим shutdown state приложения в true.
|
|
||||||
shutdown = true
|
|
||||||
|
|
||||||
if isConnected && !shutdown {
|
|
||||||
log.Debug("Try to set our presence to Unavailable and status to Offline")
|
|
||||||
|
|
||||||
// Вот тут понадобится коллекция известных пользователей, чтобы им разослать presence, что бот свалил в
|
|
||||||
// offline. Пока за неимением лучшего сообщим об этом самим себе.
|
|
||||||
for _, room := range roomsConnected {
|
|
||||||
if _, err := talk.SendPresence(
|
|
||||||
xmpp.Presence{ //nolint:exhaustruct
|
|
||||||
To: room,
|
|
||||||
Status: "Offline",
|
|
||||||
Type: "unavailable",
|
|
||||||
},
|
|
||||||
); err != nil {
|
|
||||||
log.Infof("Unable to send presence to jabber server: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// И закрываем соединение.
|
|
||||||
log.Infoln("Closing connection to jabber server")
|
|
||||||
|
|
||||||
if err := talk.Close(); err != nil {
|
|
||||||
log.Infof("Unable to close connection to jabber server: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// readWhitelist читает и валидирует белые списки пользователей.
|
|
||||||
func readWhitelist() error {
|
|
||||||
var (
|
|
||||||
whitelistLoaded = false
|
|
||||||
err error
|
|
||||||
executablePath string
|
|
||||||
)
|
|
||||||
|
|
||||||
executablePath, err = os.Executable()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("unable to get current executable path: %w", err)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
whitelistJSONPath := fmt.Sprintf("%s/data/whitelist.json", filepath.Dir(executablePath))
|
|
||||||
|
|
||||||
locations := []string{
|
|
||||||
"~/.bunyPresense-jabber-bot-whitelist.json",
|
|
||||||
"~/bunyPresense-jabber-bot-whitelist.json",
|
|
||||||
"/etc/bunyPresense-jabber-bot-whitelist.json",
|
|
||||||
whitelistJSONPath,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, location := range locations {
|
|
||||||
fileInfo, err := os.Stat(location)
|
|
||||||
|
|
||||||
// Предполагаем, что файла либо нет, либо мы не можем его прочитать, второе надо бы логгировать, но пока забьём
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Файл белого списка длинноват для белого списка, попробуем следующего кандидата
|
|
||||||
if fileInfo.Size() > 2097152 {
|
|
||||||
log.Warnf("Whitelist file %s is too long for whitelist, skipping", location)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
buf, err := os.ReadFile(location)
|
|
||||||
|
|
||||||
// Не удалось прочитать, попробуем следующего кандидата
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Skip reading whitelist file %s: %s", location, err)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Исходя из документации, hjson какбы умеет парсить "кривой" json, но парсит его в map-ку.
|
|
||||||
// Интереснее на выходе получить структурку: то есть мы вначале конфиг преобразуем в map-ку, затем эту map-ку
|
|
||||||
// сериализуем в json, а потом json превращаем в структурку. Не очень эффективно, но он и нечасто требуется.
|
|
||||||
var (
|
|
||||||
sampleWhitelist myWhiteList
|
|
||||||
tmp map[string]interface{}
|
|
||||||
)
|
|
||||||
|
|
||||||
err = hjson.Unmarshal(buf, &tmp)
|
|
||||||
|
|
||||||
// Не удалось распарсить - попробуем следующего кандидата
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Skip parsing whitelist file %s: %s", location, err)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpJSON, err := json.Marshal(tmp)
|
|
||||||
|
|
||||||
// Не удалось преобразовать map-ку в json
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Skip parsing whitelist file %s: %s", location, err)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(tmpJSON, &sampleWhitelist); err != nil {
|
|
||||||
log.Warnf("Skip parsing whitelist file %s: %s", location, err)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
whiteList = sampleWhitelist
|
|
||||||
whitelistLoaded = true
|
|
||||||
|
|
||||||
log.Infof("Using %s as whiteList file", location)
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if !whitelistLoaded {
|
|
||||||
return errors.New("whitelist was not loaded") //nolint:goerr113
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// readBlacklist читает и валидирует чёрные списки пользователей.
|
|
||||||
func readBlacklist() error {
|
|
||||||
var (
|
|
||||||
blacklistLoaded = false
|
|
||||||
err error
|
|
||||||
executablePath string
|
|
||||||
)
|
|
||||||
|
|
||||||
executablePath, err = os.Executable()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("unable to get current executable path: %w", err)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
whitelistJSONPath := fmt.Sprintf("%s/data/blacklist.json", filepath.Dir(executablePath))
|
|
||||||
|
|
||||||
locations := []string{
|
|
||||||
"~/.bunyPresense-jabber-bot-blacklist.json",
|
|
||||||
"~/bunyPresense-jabber-bot-blacklist.json",
|
|
||||||
"/etc/bunyPresense-jabber-bot-blacklist.json",
|
|
||||||
whitelistJSONPath,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, location := range locations {
|
|
||||||
fileInfo, err := os.Stat(location)
|
|
||||||
|
|
||||||
// Предполагаем, что файла либо нет, либо мы не можем его прочитать, второе надо бы логгировать, но пока забьём
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Файл чёрного списка длинноват для чёрного списка, попробуем следующего кандидата
|
|
||||||
if fileInfo.Size() > 16777216 {
|
|
||||||
log.Warnf("Blacklist file %s is too long for blacklist, skipping", location)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
buf, err := os.ReadFile(location)
|
|
||||||
|
|
||||||
// Не удалось прочитать, попробуем следующего кандидата
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Skip reading blacklist file %s: %s", location, err)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Исходя из документации, hjson какбы умеет парсить "кривой" json, но парсит его в map-ку.
|
|
||||||
// Интереснее на выходе получить структурку: то есть мы вначале конфиг преобразуем в map-ку, затем эту map-ку
|
|
||||||
// сериализуем в json, а потом json превращаем в структурку. Не очень эффективно, но он и нечасто требуется.
|
|
||||||
var (
|
|
||||||
sampleBlacklist myBlackList
|
|
||||||
tmp map[string]interface{}
|
|
||||||
)
|
|
||||||
|
|
||||||
err = hjson.Unmarshal(buf, &tmp)
|
|
||||||
|
|
||||||
// Не удалось распарсить - попробуем следующего кандидата
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Skip parsing blacklist file %s: %s", location, err)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpJSON, err := json.Marshal(tmp)
|
|
||||||
|
|
||||||
// Не удалось преобразовать map-ку в json
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Skip parsing blacklist file %s: %s", location, err)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(tmpJSON, &sampleBlacklist); err != nil {
|
|
||||||
log.Warnf("Skip parsing whitelist file %s: %s", location, err)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
blackList = sampleBlacklist
|
|
||||||
blacklistLoaded = true
|
|
||||||
|
|
||||||
log.Infof("Using %s as blacklist file", location)
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if !blacklistLoaded {
|
|
||||||
return errors.New("blacklist was not loaded") //nolint:goerr113
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// establishConnection устанавливает соединение с jabber-сервером.
|
|
||||||
func establishConnection() {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if connecting && !isConnected {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Проставляем глобальные переменные.
|
|
||||||
connecting = true
|
|
||||||
isConnected = false
|
|
||||||
roomsConnected = make([]string, 0)
|
|
||||||
|
|
||||||
log.Debugf("Establishing connection to %s", options.Host)
|
|
||||||
talk, err = options.NewClient()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
gTomb.Kill(err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// По идее keepalive должен же проходить только, если мы уже на сервере, так?
|
|
||||||
if _, err := talk.SendKeepAlive(); err != nil {
|
|
||||||
log.Errorf("Try to send initial KeepAlive, got error: %s", err)
|
|
||||||
|
|
||||||
gTomb.Kill(err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info("Connected")
|
|
||||||
|
|
||||||
// Джойнимся к чятикам, но делаем это в фоне, чтобы не блочиться на ошибках, например, если бота забанили
|
|
||||||
for _, roomStruct := range config.Jabber.Channels {
|
|
||||||
room := roomStruct.Name
|
|
||||||
go joinMuc(room)
|
|
||||||
}
|
|
||||||
|
|
||||||
go RotateStatus("")
|
|
||||||
|
|
||||||
lastActivity = time.Now().Unix()
|
|
||||||
connecting = false
|
|
||||||
isConnected = true
|
|
||||||
|
|
||||||
log.Debugf("Sending disco#info to %s", config.Jabber.Server)
|
|
||||||
|
|
||||||
_, err = talk.DiscoverInfo(talk.JID(), config.Jabber.Server)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Infof("Unable to send disco#info to jabber server: %s", err)
|
|
||||||
gTomb.Kill(err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// joinMuс джойнится к конференциям/каналам/комнатам в джаббере.
|
|
||||||
func joinMuc(room string) {
|
|
||||||
log.Debugf("Sending disco#info from %s to %s", talk.JID(), room)
|
|
||||||
|
|
||||||
if _, err := talk.DiscoverInfo(talk.JID(), room); err != nil {
|
|
||||||
log.Infof("Unable to send disco#info to MUC %s: %s", room, err)
|
|
||||||
|
|
||||||
gTomb.Kill(err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ждём, пока muc нам вернёт список фичей.
|
|
||||||
for i := 0; i < (20 * int(config.Jabber.ConnectionTimeout)); i++ {
|
|
||||||
var (
|
|
||||||
myRoom interface{}
|
|
||||||
supported bool
|
|
||||||
exist bool
|
|
||||||
)
|
|
||||||
|
|
||||||
time.Sleep(50 * time.Millisecond)
|
|
||||||
|
|
||||||
if myRoom, exist = mucCapsList.Get(room); !exist {
|
|
||||||
// Пока не задискаверилась
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if supported, exist = myRoom.(map[string]bool)["muc_unsecured"]; exist {
|
|
||||||
if supported {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("Unable to join to password-protected room. Don't know how to enter passwords :)")
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Заходим в конфу, наконец-то
|
|
||||||
if _, err := talk.JoinMUCNoHistory(room, getBotNickFromRoomConfig(room)); err != nil {
|
|
||||||
log.Errorf("Unable to join to MUC: %s", room)
|
|
||||||
|
|
||||||
gTomb.Kill(err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("Joining to MUC: %s", room)
|
|
||||||
|
|
||||||
// Ждём, когда прилетит presence из комнаты, тогда мы точно знаем, что мы вошли.
|
|
||||||
entered := false
|
|
||||||
|
|
||||||
for i := 0; i < (20 * int(config.Jabber.ConnectionTimeout)); i++ {
|
|
||||||
time.Sleep(50 * time.Millisecond)
|
|
||||||
|
|
||||||
if slices.Contains(roomsConnected, room) {
|
|
||||||
entered = true
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !entered {
|
|
||||||
log.Errorf(
|
|
||||||
"Unable to enter to MUC %s, join timeout after %d seconds (server does not return my presence for this room)",
|
|
||||||
room,
|
|
||||||
20*int(config.Jabber.ConnectionTimeout)+1,
|
|
||||||
)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Вот теперь точно можно слать статус.
|
|
||||||
log.Infof("Joined to MUC: %s", room)
|
|
||||||
|
|
||||||
go RotateStatus(room)
|
|
||||||
|
|
||||||
// Время проверить участников на предмет злобности
|
|
||||||
namesInterface, present := roomPresences.Get(room)
|
|
||||||
|
|
||||||
// Если room есть в списке presence-ов, то фигачим. room там должен быть, просто обязан.
|
|
||||||
if present {
|
|
||||||
for _, name := range interfaceToStringSlice(namesInterface) {
|
|
||||||
var v xmpp.Presence
|
|
||||||
|
|
||||||
_ = json.Unmarshal([]byte(name), &v)
|
|
||||||
log.Infof("Fake presence forged for %s just for on-enter check", name)
|
|
||||||
// Оно там внутри всё само обработает, если вдруг возникнет wire error, то зарекконетится.
|
|
||||||
_ = bunyPresense(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// probeServerLiveness проверяет живость соединения с сервером. Для многих серверов обязательная штука, без которой
|
|
||||||
// они выкидывают (дисконнектят) клиента через некоторое время неактивности.
|
|
||||||
func probeServerLiveness() { //nolint:gocognit
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-gTomb.Dying():
|
|
||||||
gTomb.Done()
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
default:
|
|
||||||
for {
|
|
||||||
if shutdown {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sleepTime := time.Duration(config.Jabber.ServerPingDelay) * 1000 * time.Millisecond
|
|
||||||
sleepTime += time.Duration(rand.Int63n(1000*config.Jabber.PingSplayDelay)) * time.Millisecond
|
|
||||||
time.Sleep(sleepTime)
|
|
||||||
|
|
||||||
if !isConnected {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Пингуем, только если не было никакой активности в течение > config.Jabber.ServerPingDelay,
|
|
||||||
// в худшем случе это будет ~ (config.Jabber.PingSplayDelay * 2) + config.Jabber.PingSplayDelay
|
|
||||||
// if (time.Now().Unix() - lastServerActivity) < (config.Jabber.ServerPingDelay + config.Jabber.PingSplayDelay) {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
|
|
||||||
if serverCapsQueried { // Сервер ответил на disco#info
|
|
||||||
var (
|
|
||||||
value interface{}
|
|
||||||
exist bool
|
|
||||||
)
|
|
||||||
|
|
||||||
value, exist = serverCapsList.Get("urn:xmpp:ping")
|
|
||||||
|
|
||||||
switch {
|
|
||||||
// Сервер анонсировал, что умеет в c2s пинги
|
|
||||||
case exist && value.(bool):
|
|
||||||
// Таймаут c2s пинга. Возьмём сумму задержки между пингами, добавим таймаут коннекта и добавим
|
|
||||||
// максимальную корректировку разброса.
|
|
||||||
txTimeout := config.Jabber.ServerPingDelay + config.Jabber.ConnectionTimeout
|
|
||||||
txTimeout += config.Jabber.PingSplayDelay
|
|
||||||
rxTimeout := txTimeout
|
|
||||||
|
|
||||||
rxTimeAgo := time.Now().Unix() - serverPingTimestampRx
|
|
||||||
|
|
||||||
if serverPingTimestampTx > 0 { // Первая пуля от нас ушла...
|
|
||||||
switch {
|
|
||||||
// Давненько мы не получали понгов от сервера, вероятно, соединение с сервером утеряно?
|
|
||||||
case rxTimeAgo > (rxTimeout * 2):
|
|
||||||
err := fmt.Errorf( //nolint:goerr113
|
|
||||||
"stall connection detected. No c2s pong for %d seconds",
|
|
||||||
rxTimeAgo,
|
|
||||||
)
|
|
||||||
|
|
||||||
gTomb.Kill(err)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
// По-умолчанию, мы отправляем c2s пинг
|
|
||||||
default:
|
|
||||||
log.Debugf("Sending c2s ping from %s to %s", talk.JID(), config.Jabber.Server)
|
|
||||||
|
|
||||||
if err := talk.PingC2S(talk.JID(), config.Jabber.Server); err != nil {
|
|
||||||
gTomb.Kill(err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
serverPingTimestampTx = time.Now().Unix()
|
|
||||||
}
|
|
||||||
} else { // Первая пуля пока не вылетела, отправляем
|
|
||||||
log.Debugf("Sending first c2s ping from %s to %s", talk.JID(), config.Jabber.Server)
|
|
||||||
|
|
||||||
if err := talk.PingC2S(talk.JID(), config.Jabber.Server); err != nil {
|
|
||||||
gTomb.Kill(err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
serverPingTimestampTx = time.Now().Unix()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Сервер не анонсировал, что умеет в c2s пинги
|
|
||||||
default:
|
|
||||||
log.Debug("Sending keepalive whitespace ping")
|
|
||||||
|
|
||||||
if _, err := talk.SendKeepAlive(); err != nil {
|
|
||||||
gTomb.Kill(err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { // Сервер не ответил на disco#info
|
|
||||||
log.Debug("Sending keepalive whitespace ping")
|
|
||||||
|
|
||||||
if _, err := talk.SendKeepAlive(); err != nil {
|
|
||||||
gTomb.Kill(err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// probeMUCLiveness Пингует MUC-и, нужно для проверки, что клиент ещё находится в MUC-е.
|
|
||||||
func probeMUCLiveness() { //nolint:gocognit
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-gTomb.Dying():
|
|
||||||
gTomb.Done()
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
default:
|
|
||||||
for {
|
|
||||||
for _, room := range roomsConnected {
|
|
||||||
var (
|
|
||||||
exist bool
|
|
||||||
lastActivityTS interface{}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Если записи про комнату нету, то пинговать её бессмысленно.
|
|
||||||
if lastActivityTS, exist = lastMucActivity.Get(room); !exist {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Если время последней активности в чятике не превысило
|
|
||||||
// config.Jabber.ServerPingDelay + config.Jabber.PingSplayDelay, ничего не пингуем.
|
|
||||||
if (time.Now().Unix() - lastActivityTS.(int64)) < (config.Jabber.ServerPingDelay + config.Jabber.PingSplayDelay) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Пинг MUC-а по сценарию без серверной оптимизации мы реализовывать не будем. Это как-то не надёжно.
|
|
||||||
go func(room string) {
|
|
||||||
// Небольшая рандомная задержка перед пингом комнаты
|
|
||||||
sleepTime := time.Duration(rand.Int63n(1000*config.Jabber.PingSplayDelay)) * time.Millisecond //nolint:gosec
|
|
||||||
time.Sleep(sleepTime)
|
|
||||||
|
|
||||||
if err := talk.PingS2S(talk.JID(), room+"/"+getBotNickFromRoomConfig(room)); err != nil {
|
|
||||||
gTomb.Kill(err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}(room)
|
|
||||||
*/
|
|
||||||
var roomMap interface{}
|
|
||||||
|
|
||||||
roomMap, exist = mucCapsList.Get(room)
|
|
||||||
|
|
||||||
// Пинги комнаты проводим, только если она записана, как прошедшая disco#info и поддерживающая
|
|
||||||
// Server Optimization.
|
|
||||||
if exist && roomMap.(map[string]bool)["http://jabber.org/protocol/muc#self-ping-optimization"] {
|
|
||||||
go func(room string) {
|
|
||||||
// Небольшая рандомная задержка перед пингом комнаты.
|
|
||||||
sleepTime := time.Duration(rand.Int63n(1000*config.Jabber.PingSplayDelay)) * time.Millisecond
|
|
||||||
time.Sleep(sleepTime)
|
|
||||||
|
|
||||||
log.Debugf("Sending MUC ping from %s to %s", talk.JID(), room)
|
|
||||||
|
|
||||||
if err := talk.PingS2S(talk.JID(), room); err != nil {
|
|
||||||
err := fmt.Errorf("unable to ping MUC %s: %w", room, err)
|
|
||||||
gTomb.Kill(err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}(room)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(time.Duration(config.Jabber.MucPingDelay) * time.Second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RotateStatus периодически изменяет статус бота в MUC-е согласно настройкам из кофига.
|
|
||||||
func RotateStatus(room string) {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-gTomb.Dying():
|
|
||||||
gTomb.Done()
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
default:
|
|
||||||
// TODO: Переделать на ticker-ы
|
|
||||||
totalSleepTime := time.Duration(config.Jabber.RuntimeStatus.RotationTime) * time.Second
|
|
||||||
totalSleepTime += time.Duration(config.Jabber.RuntimeStatus.RotationSplayTime) * time.Second
|
|
||||||
|
|
||||||
for {
|
|
||||||
status := randomPhrase(config.Jabber.RuntimeStatus.Text)
|
|
||||||
log.Debugf("Set status for MUC: %s to: %s", room, status)
|
|
||||||
|
|
||||||
var p xmpp.Presence
|
|
||||||
|
|
||||||
if room != "" {
|
|
||||||
p = xmpp.Presence{ //nolint:exhaustruct
|
|
||||||
To: room,
|
|
||||||
Status: status,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
p = xmpp.Presence{ //nolint:exhaustruct
|
|
||||||
Status: status,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := talk.SendPresence(p); err != nil {
|
|
||||||
log.Infof("Unable to send presence to MUC %s: %s", room, err)
|
|
||||||
gTomb.Kill(err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Если мы не хотим ротировать, то цикл нам тут не нужен, просто выходим.
|
|
||||||
if config.Jabber.RuntimeStatus.RotationTime == 0 {
|
|
||||||
gTomb.Done()
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(totalSleepTime)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// randomPhrase Выдаёт одну рандомную фразу из даденного списка фраз.
|
|
||||||
func randomPhrase(list []string) string {
|
|
||||||
phrase := ""
|
|
||||||
|
|
||||||
if listLen := len(list); listLen > 0 {
|
|
||||||
phrase = list[rand.Intn(listLen)]
|
|
||||||
}
|
|
||||||
|
|
||||||
return phrase
|
|
||||||
}
|
|
||||||
|
|
||||||
// interfaceToStringSlice превращает данный интерфейс в слайс строк.
|
|
||||||
// Если может, конечно :) .
|
|
||||||
func interfaceToStringSlice(iface interface{}) []string {
|
|
||||||
var mySlice []string
|
|
||||||
|
|
||||||
// А теперь мы начинаем дурдом, нам надо превратить ёбанный interface{} в []string
|
|
||||||
// Поскольку interface{} может быть чем угодно, перестрахуемся
|
|
||||||
if reflect.TypeOf(iface).Kind() == reflect.Slice {
|
|
||||||
shit := reflect.ValueOf(iface)
|
|
||||||
|
|
||||||
for i := 0; i < shit.Len(); i++ {
|
|
||||||
mySlice = append(mySlice, fmt.Sprint(shit.Index(i)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mySlice
|
|
||||||
}
|
|
||||||
|
|
||||||
// getRealJIDfromNick достаёт из запомненных presence-ов по даденному nick-у real jid с resource-ом. Nick должен
|
|
||||||
// содержать имя конфы, откуда участник.
|
|
||||||
func getRealJIDfromNick(fullNick string) string {
|
|
||||||
var p xmpp.Presence
|
|
||||||
|
|
||||||
room := (strings.SplitN(fullNick, "/", 2))[0]
|
|
||||||
|
|
||||||
// Достанем presence участника
|
|
||||||
presenceJSONInterface, present := roomPresences.Get(room)
|
|
||||||
|
|
||||||
// Никого нет дома
|
|
||||||
if !present {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
presenceJSONStrings := interfaceToStringSlice(presenceJSONInterface)
|
|
||||||
|
|
||||||
for _, presepresenceJSONString := range presenceJSONStrings {
|
|
||||||
_ = json.Unmarshal([]byte(presepresenceJSONString), &p)
|
|
||||||
|
|
||||||
if p.From == fullNick {
|
|
||||||
return p.JID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// getBotNickFromRoomConfig достаёт из настроек комнаты короткий ник бота, либо берёт значение из конфига, если ник в
|
|
||||||
// настройках комнаты не задан. Короткий ник не содержит название комнаты.
|
|
||||||
func getBotNickFromRoomConfig(room string) string {
|
|
||||||
for _, roomStruct := range config.Jabber.Channels {
|
|
||||||
if roomStruct.Name == room {
|
|
||||||
return roomStruct.Nick
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return config.Jabber.Nick
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
|
||||||
227
main.go
227
main.go
@@ -1,227 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/eleksir/go-xmpp"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"gopkg.in/tomb.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// init начальная подготовка: чтение и валидация конфига, инициализация логгера.
|
|
||||||
func init() {
|
|
||||||
log.SetFormatter(&log.TextFormatter{ //nolint:exhaustruct
|
|
||||||
DisableQuote: true,
|
|
||||||
DisableLevelTruncation: false,
|
|
||||||
DisableColors: true,
|
|
||||||
FullTimestamp: true,
|
|
||||||
TimestampFormat: "2006-01-02 15:04:05",
|
|
||||||
})
|
|
||||||
|
|
||||||
if err := readConfig(); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// no panic
|
|
||||||
switch config.Loglevel {
|
|
||||||
case "fatal":
|
|
||||||
log.SetLevel(log.FatalLevel)
|
|
||||||
case "error":
|
|
||||||
log.SetLevel(log.ErrorLevel)
|
|
||||||
case "warn":
|
|
||||||
log.SetLevel(log.WarnLevel)
|
|
||||||
case "info":
|
|
||||||
log.SetLevel(log.InfoLevel)
|
|
||||||
case "debug":
|
|
||||||
log.SetLevel(log.DebugLevel)
|
|
||||||
case "trace":
|
|
||||||
log.SetLevel(log.TraceLevel)
|
|
||||||
default:
|
|
||||||
log.SetLevel(log.InfoLevel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// main - фактичеcки начало и основное тело программы.
|
|
||||||
func main() {
|
|
||||||
// Откроем лог и скормим его логгеру.
|
|
||||||
if config.Log != "" {
|
|
||||||
logfile, err := os.OpenFile(config.Log, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Unable to open log file %s: %s", config.Log, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.SetOutput(logfile)
|
|
||||||
}
|
|
||||||
|
|
||||||
myLogLevel := log.GetLevel()
|
|
||||||
log.Warnf("Loglevel set to %v", myLogLevel)
|
|
||||||
|
|
||||||
verboseClient := false
|
|
||||||
|
|
||||||
if myLogLevel == log.TraceLevel {
|
|
||||||
verboseClient = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Самое время вгрузить белые и чёрные списки, если что - получим ошибку в лог.
|
|
||||||
if err := readWhitelist(); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := readBlacklist(); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// github.com/mattn/go-xmpp пишет в stdio, нам этого не надо, ловим выхлоп его в logrus с уровнем trace.
|
|
||||||
xmpp.DebugWriter = log.WithFields(log.Fields{"logger": "stdlib"}).WriterLevel(log.TraceLevel)
|
|
||||||
|
|
||||||
// Хэндлер сигналов не надо трогать, он нужен для завершения программы целиком.
|
|
||||||
go sigHandler()
|
|
||||||
signal.Notify(sigChan, os.Interrupt)
|
|
||||||
|
|
||||||
// Враппер основной программы. Фактически на каждой серьёзной ошибке, например, сетевой, mainLoop и некоторые
|
|
||||||
// вспомогательные корутины прекращает свою работу. Здесь мы это ловим и запускаем их снова. Задача в том, чтобы
|
|
||||||
// запустить все асинхронные процессы заново, с чистого листа, но уже с распарсенным конфигом.
|
|
||||||
for {
|
|
||||||
options = &xmpp.Options{ //nolint:exhaustruct
|
|
||||||
Host: fmt.Sprintf("%s:%d", config.Jabber.Server, config.Jabber.Port),
|
|
||||||
User: config.Jabber.User,
|
|
||||||
Password: config.Jabber.Password,
|
|
||||||
Resource: config.Jabber.Resource,
|
|
||||||
NoTLS: !config.Jabber.Ssl,
|
|
||||||
StartTLS: config.Jabber.StartTLS,
|
|
||||||
TLSConfig: &tls.Config{ //nolint:exhaustruct
|
|
||||||
ServerName: config.Jabber.Server,
|
|
||||||
InsecureSkipVerify: !config.Jabber.SslVerify, //nolint:gosec
|
|
||||||
},
|
|
||||||
InsecureAllowUnencryptedAuth: config.Jabber.InsecureAllowUnencryptedAuth,
|
|
||||||
Debug: verboseClient,
|
|
||||||
Session: false,
|
|
||||||
Status: "xa",
|
|
||||||
StatusMessage: randomPhrase(config.Jabber.StartupStatus),
|
|
||||||
DialTimeout: time.Duration(config.Jabber.ConnectionTimeout) * time.Second,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Через tomb попробуем сделать завершение горутинок управляемым.
|
|
||||||
gTomb = tomb.Tomb{}
|
|
||||||
|
|
||||||
// Устанавливаем соединение и гребём события, посылаемые сервером - основной и вспомогательные циклы программы.
|
|
||||||
myLoop()
|
|
||||||
|
|
||||||
// Логгируем причину завершения mainLoop и вспомогательных циклов программы.
|
|
||||||
log.Error(gTomb.Wait())
|
|
||||||
|
|
||||||
// Если у нас wire error, то вызов .Close() повлечёт за собой ошибку, но мы вынуждены звать .Close(), чтоб
|
|
||||||
// закрыть tls контекст и почистить всё что связанно с прерванным соединением.
|
|
||||||
log.Infoln("Closing connection to jabber server")
|
|
||||||
|
|
||||||
_ = talk.Close()
|
|
||||||
|
|
||||||
time.Sleep(time.Duration(config.Jabber.ReconnectDelay) * time.Second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Основной цикл программы.
|
|
||||||
func myLoop() {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-gTomb.Dying():
|
|
||||||
gTomb.Done()
|
|
||||||
return //nolint:nlreturn
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Зададим начальное значение глобальным переменным
|
|
||||||
serverPingTimestampRx = 0
|
|
||||||
serverPingTimestampTx = 0
|
|
||||||
roomsConnected = make([]string, 1)
|
|
||||||
lastActivity = 0
|
|
||||||
lastServerActivity = 0
|
|
||||||
lastMucActivity = NewCollection()
|
|
||||||
serverCapsQueried = false
|
|
||||||
serverCapsList = NewCollection()
|
|
||||||
mucCapsList = NewCollection()
|
|
||||||
serverPingTimestampTx = 0
|
|
||||||
serverPingTimestampRx = 0
|
|
||||||
roomPresences = NewCollection()
|
|
||||||
|
|
||||||
// Установим коннект
|
|
||||||
establishConnection()
|
|
||||||
|
|
||||||
serverPingTimestampRx = time.Now().Unix() // Считаем, что если коннект запустился, то первый пинг успешен.
|
|
||||||
|
|
||||||
// Тыкаем сервер палочкой, проверяем, что коннект жив и вываливаемся из mainLoop, если он не жив.
|
|
||||||
go probeServerLiveness()
|
|
||||||
|
|
||||||
// Тыкаем muc-и палочкой, проверяем, что они живы и вываливаемся из mainLoop, если пинги пропали.
|
|
||||||
// Если пинги до комнаты пропали, то это фактически значит, что либо сервер потерял связь с MUC-компонентом,
|
|
||||||
// либо у нас какой-то wire error.
|
|
||||||
go probeMUCLiveness()
|
|
||||||
|
|
||||||
// Гребём ивенты...
|
|
||||||
for {
|
|
||||||
// Стриггерилось завершение работы приложения, или соединение не установлено (порвалось, например)
|
|
||||||
// грести не надо
|
|
||||||
if shutdown {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isConnected {
|
|
||||||
// Tight loop - это наверно не очень хорошо, думаю, ничего страшного не будет, если мы поспим 100мс.
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Вынимаем ивент из "провода"
|
|
||||||
chat, err := talk.Recv()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Unable to get events from server: %s", err)
|
|
||||||
|
|
||||||
// Попробуем скрасить печальные будни generic-ошибок...
|
|
||||||
switch {
|
|
||||||
// Стрим не читается, он закрылся с той стороны во время чтения
|
|
||||||
case errors.Is(err, io.EOF):
|
|
||||||
err = fmt.Errorf("tcp stream closed while reading, err=%w", err)
|
|
||||||
|
|
||||||
// Пытаемся читать закрытый сокет
|
|
||||||
case errors.Is(err, net.ErrClosed):
|
|
||||||
err = fmt.Errorf("unable to read closed socket, err=%w", err)
|
|
||||||
|
|
||||||
// Не смогли записать в сокет
|
|
||||||
case errors.Is(err, net.ErrWriteToConnected):
|
|
||||||
err = fmt.Errorf("unable to write to socket, err=%w", err)
|
|
||||||
|
|
||||||
// Не сетевая проблема
|
|
||||||
default:
|
|
||||||
// Это уже что-то странное.
|
|
||||||
// Вероятно, ошибка парсинга xml. Собственно, баг сервера, тут мы ничего поделать не можем.
|
|
||||||
err = fmt.Errorf("error during parsing received message, err=%w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
gTomb.Kill(err)
|
|
||||||
|
|
||||||
// Не забываем выходить на ошибке :(
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
parseEvent(chat)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
|
||||||
2
vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
generated
vendored
2
vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
generated
vendored
@@ -16,7 +16,7 @@ Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
|
|||||||
choose, you can pass the `New` functions from the different SHA packages to
|
choose, you can pass the `New` functions from the different SHA packages to
|
||||||
pbkdf2.Key.
|
pbkdf2.Key.
|
||||||
*/
|
*/
|
||||||
package pbkdf2
|
package pbkdf2 // import "golang.org/x/crypto/pbkdf2"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
|
|||||||
30
vendor/golang.org/x/sys/internal/unsafeheader/unsafeheader.go
generated
vendored
Normal file
30
vendor/golang.org/x/sys/internal/unsafeheader/unsafeheader.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package unsafeheader contains header declarations for the Go runtime's
|
||||||
|
// slice and string implementations.
|
||||||
|
//
|
||||||
|
// This package allows x/sys to use types equivalent to
|
||||||
|
// reflect.SliceHeader and reflect.StringHeader without introducing
|
||||||
|
// a dependency on the (relatively heavy) "reflect" package.
|
||||||
|
package unsafeheader
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Slice is the runtime representation of a slice.
|
||||||
|
// It cannot be used safely or portably and its representation may change in a later release.
|
||||||
|
type Slice struct {
|
||||||
|
Data unsafe.Pointer
|
||||||
|
Len int
|
||||||
|
Cap int
|
||||||
|
}
|
||||||
|
|
||||||
|
// String is the runtime representation of a string.
|
||||||
|
// It cannot be used safely or portably and its representation may change in a later release.
|
||||||
|
type String struct {
|
||||||
|
Data unsafe.Pointer
|
||||||
|
Len int
|
||||||
|
}
|
||||||
4
vendor/golang.org/x/sys/unix/aliases.go
generated
vendored
4
vendor/golang.org/x/sys/unix/aliases.go
generated
vendored
@@ -2,7 +2,9 @@
|
|||||||
// 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 || zos
|
//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
// +build go1.9
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
generated
vendored
1
vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gc
|
//go:build gc
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
2
vendor/golang.org/x/sys/unix/asm_bsd_386.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_386.s
generated
vendored
@@ -3,6 +3,8 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (freebsd || netbsd || openbsd) && gc
|
//go:build (freebsd || netbsd || openbsd) && gc
|
||||||
|
// +build freebsd netbsd openbsd
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
2
vendor/golang.org/x/sys/unix/asm_bsd_amd64.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_amd64.s
generated
vendored
@@ -3,6 +3,8 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && gc
|
//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && gc
|
||||||
|
// +build darwin dragonfly freebsd netbsd openbsd
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
2
vendor/golang.org/x/sys/unix/asm_bsd_arm.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_arm.s
generated
vendored
@@ -3,6 +3,8 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (freebsd || netbsd || openbsd) && gc
|
//go:build (freebsd || netbsd || openbsd) && gc
|
||||||
|
// +build freebsd netbsd openbsd
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
2
vendor/golang.org/x/sys/unix/asm_bsd_arm64.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_arm64.s
generated
vendored
@@ -3,6 +3,8 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||||
|
// +build darwin freebsd netbsd openbsd
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
2
vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s
generated
vendored
@@ -3,6 +3,8 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||||
|
// +build darwin freebsd netbsd openbsd
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
2
vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s
generated
vendored
@@ -3,6 +3,8 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||||
|
// +build darwin freebsd netbsd openbsd
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/asm_linux_386.s
generated
vendored
1
vendor/golang.org/x/sys/unix/asm_linux_386.s
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gc
|
//go:build gc
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/asm_linux_amd64.s
generated
vendored
1
vendor/golang.org/x/sys/unix/asm_linux_amd64.s
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gc
|
//go:build gc
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/asm_linux_arm.s
generated
vendored
1
vendor/golang.org/x/sys/unix/asm_linux_arm.s
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gc
|
//go:build gc
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
3
vendor/golang.org/x/sys/unix/asm_linux_arm64.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_arm64.s
generated
vendored
@@ -3,6 +3,9 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build linux && arm64 && gc
|
//go:build linux && arm64 && gc
|
||||||
|
// +build linux
|
||||||
|
// +build arm64
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
3
vendor/golang.org/x/sys/unix/asm_linux_loong64.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_loong64.s
generated
vendored
@@ -3,6 +3,9 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build linux && loong64 && gc
|
//go:build linux && loong64 && gc
|
||||||
|
// +build linux
|
||||||
|
// +build loong64
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
3
vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
generated
vendored
@@ -3,6 +3,9 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build linux && (mips64 || mips64le) && gc
|
//go:build linux && (mips64 || mips64le) && gc
|
||||||
|
// +build linux
|
||||||
|
// +build mips64 mips64le
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
3
vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
generated
vendored
@@ -3,6 +3,9 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build linux && (mips || mipsle) && gc
|
//go:build linux && (mips || mipsle) && gc
|
||||||
|
// +build linux
|
||||||
|
// +build mips mipsle
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
3
vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
generated
vendored
@@ -3,6 +3,9 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build linux && (ppc64 || ppc64le) && gc
|
//go:build linux && (ppc64 || ppc64le) && gc
|
||||||
|
// +build linux
|
||||||
|
// +build ppc64 ppc64le
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
2
vendor/golang.org/x/sys/unix/asm_linux_riscv64.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_linux_riscv64.s
generated
vendored
@@ -3,6 +3,8 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build riscv64 && gc
|
//go:build riscv64 && gc
|
||||||
|
// +build riscv64
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
3
vendor/golang.org/x/sys/unix/asm_linux_s390x.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_s390x.s
generated
vendored
@@ -3,6 +3,9 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build linux && s390x && gc
|
//go:build linux && s390x && gc
|
||||||
|
// +build linux
|
||||||
|
// +build s390x
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s
generated
vendored
1
vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gc
|
//go:build gc
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
generated
vendored
1
vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gc
|
//go:build gc
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|||||||
580
vendor/golang.org/x/sys/unix/asm_zos_s390x.s
generated
vendored
580
vendor/golang.org/x/sys/unix/asm_zos_s390x.s
generated
vendored
@@ -3,17 +3,18 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build zos && s390x && gc
|
//go:build zos && s390x && gc
|
||||||
|
// +build zos
|
||||||
|
// +build s390x
|
||||||
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
#define PSALAA 1208(R0)
|
#define PSALAA 1208(R0)
|
||||||
#define GTAB64(x) 80(x)
|
#define GTAB64(x) 80(x)
|
||||||
#define LCA64(x) 88(x)
|
#define LCA64(x) 88(x)
|
||||||
#define SAVSTACK_ASYNC(x) 336(x) // in the LCA
|
|
||||||
#define CAA(x) 8(x)
|
#define CAA(x) 8(x)
|
||||||
#define CEECAATHDID(x) 976(x) // in the CAA
|
|
||||||
#define EDCHPXV(x) 1016(x) // in the CAA
|
#define EDCHPXV(x) 1016(x) // in the CAA
|
||||||
#define GOCB(x) 1104(x) // in the CAA
|
#define SAVSTACK_ASYNC(x) 336(x) // in the LCA
|
||||||
|
|
||||||
// SS_*, where x=SAVSTACK_ASYNC
|
// SS_*, where x=SAVSTACK_ASYNC
|
||||||
#define SS_LE(x) 0(x)
|
#define SS_LE(x) 0(x)
|
||||||
@@ -21,38 +22,15 @@
|
|||||||
#define SS_ERRNO(x) 16(x)
|
#define SS_ERRNO(x) 16(x)
|
||||||
#define SS_ERRNOJR(x) 20(x)
|
#define SS_ERRNOJR(x) 20(x)
|
||||||
|
|
||||||
// Function Descriptor Offsets
|
#define LE_CALL BYTE $0x0D; BYTE $0x76; // BL R7, R6
|
||||||
#define __errno 0x156*16
|
|
||||||
#define __err2ad 0x16C*16
|
|
||||||
|
|
||||||
// Call Instructions
|
TEXT ·clearErrno(SB),NOSPLIT,$0-0
|
||||||
#define LE_CALL BYTE $0x0D; BYTE $0x76 // BL R7, R6
|
|
||||||
#define SVC_LOAD BYTE $0x0A; BYTE $0x08 // SVC 08 LOAD
|
|
||||||
#define SVC_DELETE BYTE $0x0A; BYTE $0x09 // SVC 09 DELETE
|
|
||||||
|
|
||||||
DATA zosLibVec<>(SB)/8, $0
|
|
||||||
GLOBL zosLibVec<>(SB), NOPTR, $8
|
|
||||||
|
|
||||||
TEXT ·initZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
|
|
||||||
MOVW PSALAA, R8
|
|
||||||
MOVD LCA64(R8), R8
|
|
||||||
MOVD CAA(R8), R8
|
|
||||||
MOVD EDCHPXV(R8), R8
|
|
||||||
MOVD R8, zosLibVec<>(SB)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·GetZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
|
|
||||||
MOVD zosLibVec<>(SB), R8
|
|
||||||
MOVD R8, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·clearErrno(SB), NOSPLIT, $0-0
|
|
||||||
BL addrerrno<>(SB)
|
BL addrerrno<>(SB)
|
||||||
MOVD $0, 0(R3)
|
MOVD $0, 0(R3)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// Returns the address of errno in R3.
|
// Returns the address of errno in R3.
|
||||||
TEXT addrerrno<>(SB), NOSPLIT|NOFRAME, $0-0
|
TEXT addrerrno<>(SB),NOSPLIT|NOFRAME,$0-0
|
||||||
// Get library control area (LCA).
|
// Get library control area (LCA).
|
||||||
MOVW PSALAA, R8
|
MOVW PSALAA, R8
|
||||||
MOVD LCA64(R8), R8
|
MOVD LCA64(R8), R8
|
||||||
@@ -60,7 +38,7 @@ TEXT addrerrno<>(SB), NOSPLIT|NOFRAME, $0-0
|
|||||||
// Get __errno FuncDesc.
|
// Get __errno FuncDesc.
|
||||||
MOVD CAA(R8), R9
|
MOVD CAA(R8), R9
|
||||||
MOVD EDCHPXV(R9), R9
|
MOVD EDCHPXV(R9), R9
|
||||||
ADD $(__errno), R9
|
ADD $(0x156*16), R9
|
||||||
LMG 0(R9), R5, R6
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
// Switch to saved LE stack.
|
// Switch to saved LE stack.
|
||||||
@@ -77,8 +55,298 @@ TEXT addrerrno<>(SB), NOSPLIT|NOFRAME, $0-0
|
|||||||
MOVD R4, 0(R9) // Save stack pointer.
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_syscall(SB),NOSPLIT,$0-56
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+32(FP)
|
||||||
|
MOVD R0, r2+40(FP)
|
||||||
|
MOVD R0, err+48(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+48(FP)
|
||||||
|
done:
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_rawsyscall(SB),NOSPLIT,$0-56
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+32(FP)
|
||||||
|
MOVD R0, r2+40(FP)
|
||||||
|
MOVD R0, err+48(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+48(FP)
|
||||||
|
done:
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_syscall6(SB),NOSPLIT,$0-80
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Fill in parameter list.
|
||||||
|
MOVD a4+32(FP), R12
|
||||||
|
MOVD R12, (2176+24)(R4)
|
||||||
|
MOVD a5+40(FP), R12
|
||||||
|
MOVD R12, (2176+32)(R4)
|
||||||
|
MOVD a6+48(FP), R12
|
||||||
|
MOVD R12, (2176+40)(R4)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+56(FP)
|
||||||
|
MOVD R0, r2+64(FP)
|
||||||
|
MOVD R0, err+72(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+72(FP)
|
||||||
|
done:
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_rawsyscall6(SB),NOSPLIT,$0-80
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Fill in parameter list.
|
||||||
|
MOVD a4+32(FP), R12
|
||||||
|
MOVD R12, (2176+24)(R4)
|
||||||
|
MOVD a5+40(FP), R12
|
||||||
|
MOVD R12, (2176+32)(R4)
|
||||||
|
MOVD a6+48(FP), R12
|
||||||
|
MOVD R12, (2176+40)(R4)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+56(FP)
|
||||||
|
MOVD R0, r2+64(FP)
|
||||||
|
MOVD R0, err+72(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL ·rrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+72(FP)
|
||||||
|
done:
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_syscall9(SB),NOSPLIT,$0
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Fill in parameter list.
|
||||||
|
MOVD a4+32(FP), R12
|
||||||
|
MOVD R12, (2176+24)(R4)
|
||||||
|
MOVD a5+40(FP), R12
|
||||||
|
MOVD R12, (2176+32)(R4)
|
||||||
|
MOVD a6+48(FP), R12
|
||||||
|
MOVD R12, (2176+40)(R4)
|
||||||
|
MOVD a7+56(FP), R12
|
||||||
|
MOVD R12, (2176+48)(R4)
|
||||||
|
MOVD a8+64(FP), R12
|
||||||
|
MOVD R12, (2176+56)(R4)
|
||||||
|
MOVD a9+72(FP), R12
|
||||||
|
MOVD R12, (2176+64)(R4)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+80(FP)
|
||||||
|
MOVD R0, r2+88(FP)
|
||||||
|
MOVD R0, err+96(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+96(FP)
|
||||||
|
done:
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_rawsyscall9(SB),NOSPLIT,$0
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Fill in parameter list.
|
||||||
|
MOVD a4+32(FP), R12
|
||||||
|
MOVD R12, (2176+24)(R4)
|
||||||
|
MOVD a5+40(FP), R12
|
||||||
|
MOVD R12, (2176+32)(R4)
|
||||||
|
MOVD a6+48(FP), R12
|
||||||
|
MOVD R12, (2176+40)(R4)
|
||||||
|
MOVD a7+56(FP), R12
|
||||||
|
MOVD R12, (2176+48)(R4)
|
||||||
|
MOVD a8+64(FP), R12
|
||||||
|
MOVD R12, (2176+56)(R4)
|
||||||
|
MOVD a9+72(FP), R12
|
||||||
|
MOVD R12, (2176+64)(R4)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+80(FP)
|
||||||
|
MOVD R0, r2+88(FP)
|
||||||
|
MOVD R0, err+96(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+96(FP)
|
||||||
|
done:
|
||||||
|
RET
|
||||||
|
|
||||||
// func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
|
// func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
|
||||||
TEXT ·svcCall(SB), NOSPLIT, $0
|
TEXT ·svcCall(SB),NOSPLIT,$0
|
||||||
BL runtime·save_g(SB) // Save g and stack pointer
|
BL runtime·save_g(SB) // Save g and stack pointer
|
||||||
MOVW PSALAA, R8
|
MOVW PSALAA, R8
|
||||||
MOVD LCA64(R8), R8
|
MOVD LCA64(R8), R8
|
||||||
@@ -101,12 +369,13 @@ TEXT ·svcCall(SB), NOSPLIT, $0
|
|||||||
RET
|
RET
|
||||||
|
|
||||||
// func svcLoad(name *byte) unsafe.Pointer
|
// func svcLoad(name *byte) unsafe.Pointer
|
||||||
TEXT ·svcLoad(SB), NOSPLIT, $0
|
TEXT ·svcLoad(SB),NOSPLIT,$0
|
||||||
MOVD R15, R2 // Save go stack pointer
|
MOVD R15, R2 // Save go stack pointer
|
||||||
MOVD name+0(FP), R0 // Move SVC args into registers
|
MOVD name+0(FP), R0 // Move SVC args into registers
|
||||||
MOVD $0x80000000, R1
|
MOVD $0x80000000, R1
|
||||||
MOVD $0, R15
|
MOVD $0, R15
|
||||||
SVC_LOAD
|
BYTE $0x0A // SVC 08 LOAD
|
||||||
|
BYTE $0x08
|
||||||
MOVW R15, R3 // Save return code from SVC
|
MOVW R15, R3 // Save return code from SVC
|
||||||
MOVD R2, R15 // Restore go stack pointer
|
MOVD R2, R15 // Restore go stack pointer
|
||||||
CMP R3, $0 // Check SVC return code
|
CMP R3, $0 // Check SVC return code
|
||||||
@@ -114,32 +383,33 @@ TEXT ·svcLoad(SB), NOSPLIT, $0
|
|||||||
|
|
||||||
MOVD $-2, R3 // Reset last bit of entry point to zero
|
MOVD $-2, R3 // Reset last bit of entry point to zero
|
||||||
AND R0, R3
|
AND R0, R3
|
||||||
MOVD R3, ret+8(FP) // Return entry point returned by SVC
|
MOVD R3, addr+8(FP) // Return entry point returned by SVC
|
||||||
CMP R0, R3 // Check if last bit of entry point was set
|
CMP R0, R3 // Check if last bit of entry point was set
|
||||||
BNE done
|
BNE done
|
||||||
|
|
||||||
MOVD R15, R2 // Save go stack pointer
|
MOVD R15, R2 // Save go stack pointer
|
||||||
MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08)
|
MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08)
|
||||||
SVC_DELETE
|
BYTE $0x0A // SVC 09 DELETE
|
||||||
|
BYTE $0x09
|
||||||
MOVD R2, R15 // Restore go stack pointer
|
MOVD R2, R15 // Restore go stack pointer
|
||||||
|
|
||||||
error:
|
error:
|
||||||
MOVD $0, ret+8(FP) // Return 0 on failure
|
MOVD $0, addr+8(FP) // Return 0 on failure
|
||||||
|
|
||||||
done:
|
done:
|
||||||
XOR R0, R0 // Reset r0 to 0
|
XOR R0, R0 // Reset r0 to 0
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// func svcUnload(name *byte, fnptr unsafe.Pointer) int64
|
// func svcUnload(name *byte, fnptr unsafe.Pointer) int64
|
||||||
TEXT ·svcUnload(SB), NOSPLIT, $0
|
TEXT ·svcUnload(SB),NOSPLIT,$0
|
||||||
MOVD R15, R2 // Save go stack pointer
|
MOVD R15, R2 // Save go stack pointer
|
||||||
MOVD name+0(FP), R0 // Move SVC args into registers
|
MOVD name+0(FP), R0 // Move SVC args into registers
|
||||||
MOVD fnptr+8(FP), R15
|
MOVD addr+8(FP), R15
|
||||||
SVC_DELETE
|
BYTE $0x0A // SVC 09
|
||||||
|
BYTE $0x09
|
||||||
XOR R0, R0 // Reset r0 to 0
|
XOR R0, R0 // Reset r0 to 0
|
||||||
MOVD R15, R1 // Save SVC return code
|
MOVD R15, R1 // Save SVC return code
|
||||||
MOVD R2, R15 // Restore go stack pointer
|
MOVD R2, R15 // Restore go stack pointer
|
||||||
MOVD R1, ret+16(FP) // Return SVC return code
|
MOVD R1, rc+0(FP) // Return SVC return code
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// func gettid() uint64
|
// func gettid() uint64
|
||||||
@@ -150,233 +420,7 @@ TEXT ·gettid(SB), NOSPLIT, $0
|
|||||||
|
|
||||||
// Get CEECAATHDID
|
// Get CEECAATHDID
|
||||||
MOVD CAA(R8), R9
|
MOVD CAA(R8), R9
|
||||||
MOVD CEECAATHDID(R9), R9
|
MOVD 0x3D0(R9), R9
|
||||||
MOVD R9, ret+0(FP)
|
MOVD R9, ret+0(FP)
|
||||||
|
|
||||||
RET
|
RET
|
||||||
|
|
||||||
//
|
|
||||||
// Call LE function, if the return is -1
|
|
||||||
// errno and errno2 is retrieved
|
|
||||||
//
|
|
||||||
TEXT ·CallLeFuncWithErr(SB), NOSPLIT, $0
|
|
||||||
MOVW PSALAA, R8
|
|
||||||
MOVD LCA64(R8), R8
|
|
||||||
MOVD CAA(R8), R9
|
|
||||||
MOVD g, GOCB(R9)
|
|
||||||
|
|
||||||
// Restore LE stack.
|
|
||||||
MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address
|
|
||||||
MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer
|
|
||||||
|
|
||||||
MOVD parms_base+8(FP), R7 // R7 -> argument array
|
|
||||||
MOVD parms_len+16(FP), R8 // R8 number of arguments
|
|
||||||
|
|
||||||
// arg 1 ---> R1
|
|
||||||
CMP R8, $0
|
|
||||||
BEQ docall
|
|
||||||
SUB $1, R8
|
|
||||||
MOVD 0(R7), R1
|
|
||||||
|
|
||||||
// arg 2 ---> R2
|
|
||||||
CMP R8, $0
|
|
||||||
BEQ docall
|
|
||||||
SUB $1, R8
|
|
||||||
ADD $8, R7
|
|
||||||
MOVD 0(R7), R2
|
|
||||||
|
|
||||||
// arg 3 --> R3
|
|
||||||
CMP R8, $0
|
|
||||||
BEQ docall
|
|
||||||
SUB $1, R8
|
|
||||||
ADD $8, R7
|
|
||||||
MOVD 0(R7), R3
|
|
||||||
|
|
||||||
CMP R8, $0
|
|
||||||
BEQ docall
|
|
||||||
MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument
|
|
||||||
|
|
||||||
repeat:
|
|
||||||
ADD $8, R7
|
|
||||||
MOVD 0(R7), R0 // advance arg pointer by 8 byte
|
|
||||||
ADD $8, R6 // advance LE argument address by 8 byte
|
|
||||||
MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame
|
|
||||||
SUB $1, R8
|
|
||||||
CMP R8, $0
|
|
||||||
BNE repeat
|
|
||||||
|
|
||||||
docall:
|
|
||||||
MOVD funcdesc+0(FP), R8 // R8-> function descriptor
|
|
||||||
LMG 0(R8), R5, R6
|
|
||||||
MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC
|
|
||||||
LE_CALL // balr R7, R6 (return #1)
|
|
||||||
NOPH
|
|
||||||
MOVD R3, ret+32(FP)
|
|
||||||
CMP R3, $-1 // compare result to -1
|
|
||||||
BNE done
|
|
||||||
|
|
||||||
// retrieve errno and errno2
|
|
||||||
MOVD zosLibVec<>(SB), R8
|
|
||||||
ADD $(__errno), R8
|
|
||||||
LMG 0(R8), R5, R6
|
|
||||||
LE_CALL // balr R7, R6 __errno (return #3)
|
|
||||||
NOPH
|
|
||||||
MOVWZ 0(R3), R3
|
|
||||||
MOVD R3, err+48(FP)
|
|
||||||
MOVD zosLibVec<>(SB), R8
|
|
||||||
ADD $(__err2ad), R8
|
|
||||||
LMG 0(R8), R5, R6
|
|
||||||
LE_CALL // balr R7, R6 __err2ad (return #2)
|
|
||||||
NOPH
|
|
||||||
MOVW (R3), R2 // retrieve errno2
|
|
||||||
MOVD R2, errno2+40(FP) // store in return area
|
|
||||||
|
|
||||||
done:
|
|
||||||
MOVD R4, 0(R9) // Save stack pointer.
|
|
||||||
RET
|
|
||||||
|
|
||||||
//
|
|
||||||
// Call LE function, if the return is 0
|
|
||||||
// errno and errno2 is retrieved
|
|
||||||
//
|
|
||||||
TEXT ·CallLeFuncWithPtrReturn(SB), NOSPLIT, $0
|
|
||||||
MOVW PSALAA, R8
|
|
||||||
MOVD LCA64(R8), R8
|
|
||||||
MOVD CAA(R8), R9
|
|
||||||
MOVD g, GOCB(R9)
|
|
||||||
|
|
||||||
// Restore LE stack.
|
|
||||||
MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address
|
|
||||||
MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer
|
|
||||||
|
|
||||||
MOVD parms_base+8(FP), R7 // R7 -> argument array
|
|
||||||
MOVD parms_len+16(FP), R8 // R8 number of arguments
|
|
||||||
|
|
||||||
// arg 1 ---> R1
|
|
||||||
CMP R8, $0
|
|
||||||
BEQ docall
|
|
||||||
SUB $1, R8
|
|
||||||
MOVD 0(R7), R1
|
|
||||||
|
|
||||||
// arg 2 ---> R2
|
|
||||||
CMP R8, $0
|
|
||||||
BEQ docall
|
|
||||||
SUB $1, R8
|
|
||||||
ADD $8, R7
|
|
||||||
MOVD 0(R7), R2
|
|
||||||
|
|
||||||
// arg 3 --> R3
|
|
||||||
CMP R8, $0
|
|
||||||
BEQ docall
|
|
||||||
SUB $1, R8
|
|
||||||
ADD $8, R7
|
|
||||||
MOVD 0(R7), R3
|
|
||||||
|
|
||||||
CMP R8, $0
|
|
||||||
BEQ docall
|
|
||||||
MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument
|
|
||||||
|
|
||||||
repeat:
|
|
||||||
ADD $8, R7
|
|
||||||
MOVD 0(R7), R0 // advance arg pointer by 8 byte
|
|
||||||
ADD $8, R6 // advance LE argument address by 8 byte
|
|
||||||
MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame
|
|
||||||
SUB $1, R8
|
|
||||||
CMP R8, $0
|
|
||||||
BNE repeat
|
|
||||||
|
|
||||||
docall:
|
|
||||||
MOVD funcdesc+0(FP), R8 // R8-> function descriptor
|
|
||||||
LMG 0(R8), R5, R6
|
|
||||||
MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC
|
|
||||||
LE_CALL // balr R7, R6 (return #1)
|
|
||||||
NOPH
|
|
||||||
MOVD R3, ret+32(FP)
|
|
||||||
CMP R3, $0 // compare result to 0
|
|
||||||
BNE done
|
|
||||||
|
|
||||||
// retrieve errno and errno2
|
|
||||||
MOVD zosLibVec<>(SB), R8
|
|
||||||
ADD $(__errno), R8
|
|
||||||
LMG 0(R8), R5, R6
|
|
||||||
LE_CALL // balr R7, R6 __errno (return #3)
|
|
||||||
NOPH
|
|
||||||
MOVWZ 0(R3), R3
|
|
||||||
MOVD R3, err+48(FP)
|
|
||||||
MOVD zosLibVec<>(SB), R8
|
|
||||||
ADD $(__err2ad), R8
|
|
||||||
LMG 0(R8), R5, R6
|
|
||||||
LE_CALL // balr R7, R6 __err2ad (return #2)
|
|
||||||
NOPH
|
|
||||||
MOVW (R3), R2 // retrieve errno2
|
|
||||||
MOVD R2, errno2+40(FP) // store in return area
|
|
||||||
XOR R2, R2
|
|
||||||
MOVWZ R2, (R3) // clear errno2
|
|
||||||
|
|
||||||
done:
|
|
||||||
MOVD R4, 0(R9) // Save stack pointer.
|
|
||||||
RET
|
|
||||||
|
|
||||||
//
|
|
||||||
// function to test if a pointer can be safely dereferenced (content read)
|
|
||||||
// return 0 for succces
|
|
||||||
//
|
|
||||||
TEXT ·ptrtest(SB), NOSPLIT, $0-16
|
|
||||||
MOVD arg+0(FP), R10 // test pointer in R10
|
|
||||||
|
|
||||||
// set up R2 to point to CEECAADMC
|
|
||||||
BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208
|
|
||||||
BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2
|
|
||||||
BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767
|
|
||||||
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2)
|
|
||||||
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2)
|
|
||||||
BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2)
|
|
||||||
|
|
||||||
// set up R5 to point to the "shunt" path which set 1 to R3 (failure)
|
|
||||||
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3
|
|
||||||
BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1
|
|
||||||
BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1
|
|
||||||
|
|
||||||
// if r3 is not zero (failed) then branch to finish
|
|
||||||
BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3
|
|
||||||
BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2
|
|
||||||
|
|
||||||
// stomic store shunt address in R5 into CEECAADMC
|
|
||||||
BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2)
|
|
||||||
|
|
||||||
// now try reading from the test pointer in R10, if it fails it branches to the "lghi" instruction above
|
|
||||||
BYTE $0xE3; BYTE $0x9A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 9,0(10)
|
|
||||||
|
|
||||||
// finish here, restore 0 into CEECAADMC
|
|
||||||
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9
|
|
||||||
BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2)
|
|
||||||
MOVD R3, ret+8(FP) // result in R3
|
|
||||||
RET
|
|
||||||
|
|
||||||
//
|
|
||||||
// function to test if a untptr can be loaded from a pointer
|
|
||||||
// return 1: the 8-byte content
|
|
||||||
// 2: 0 for success, 1 for failure
|
|
||||||
//
|
|
||||||
// func safeload(ptr uintptr) ( value uintptr, error uintptr)
|
|
||||||
TEXT ·safeload(SB), NOSPLIT, $0-24
|
|
||||||
MOVD ptr+0(FP), R10 // test pointer in R10
|
|
||||||
MOVD $0x0, R6
|
|
||||||
BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208
|
|
||||||
BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2
|
|
||||||
BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767
|
|
||||||
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2)
|
|
||||||
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2)
|
|
||||||
BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2)
|
|
||||||
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3
|
|
||||||
BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1
|
|
||||||
BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1
|
|
||||||
BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3
|
|
||||||
BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2
|
|
||||||
BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2)
|
|
||||||
BYTE $0xE3; BYTE $0x6A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 6,0(10)
|
|
||||||
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9
|
|
||||||
BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2)
|
|
||||||
MOVD R6, value+8(FP) // result in R6
|
|
||||||
MOVD R3, error+16(FP) // error in R3
|
|
||||||
RET
|
|
||||||
|
|||||||
657
vendor/golang.org/x/sys/unix/bpxsvc_zos.go
generated
vendored
657
vendor/golang.org/x/sys/unix/bpxsvc_zos.go
generated
vendored
@@ -1,657 +0,0 @@
|
|||||||
// Copyright 2024 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build zos
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func bpxcall(plist []unsafe.Pointer, bpx_offset int64)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func A2e([]byte)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func E2a([]byte)
|
|
||||||
|
|
||||||
const (
|
|
||||||
BPX4STA = 192 // stat
|
|
||||||
BPX4FST = 104 // fstat
|
|
||||||
BPX4LST = 132 // lstat
|
|
||||||
BPX4OPN = 156 // open
|
|
||||||
BPX4CLO = 72 // close
|
|
||||||
BPX4CHR = 500 // chattr
|
|
||||||
BPX4FCR = 504 // fchattr
|
|
||||||
BPX4LCR = 1180 // lchattr
|
|
||||||
BPX4CTW = 492 // cond_timed_wait
|
|
||||||
BPX4GTH = 1056 // __getthent
|
|
||||||
BPX4PTQ = 412 // pthread_quiesc
|
|
||||||
BPX4PTR = 320 // ptrace
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
//options
|
|
||||||
//byte1
|
|
||||||
BPX_OPNFHIGH = 0x80
|
|
||||||
//byte2
|
|
||||||
BPX_OPNFEXEC = 0x80
|
|
||||||
//byte3
|
|
||||||
BPX_O_NOLARGEFILE = 0x08
|
|
||||||
BPX_O_LARGEFILE = 0x04
|
|
||||||
BPX_O_ASYNCSIG = 0x02
|
|
||||||
BPX_O_SYNC = 0x01
|
|
||||||
//byte4
|
|
||||||
BPX_O_CREXCL = 0xc0
|
|
||||||
BPX_O_CREAT = 0x80
|
|
||||||
BPX_O_EXCL = 0x40
|
|
||||||
BPX_O_NOCTTY = 0x20
|
|
||||||
BPX_O_TRUNC = 0x10
|
|
||||||
BPX_O_APPEND = 0x08
|
|
||||||
BPX_O_NONBLOCK = 0x04
|
|
||||||
BPX_FNDELAY = 0x04
|
|
||||||
BPX_O_RDWR = 0x03
|
|
||||||
BPX_O_RDONLY = 0x02
|
|
||||||
BPX_O_WRONLY = 0x01
|
|
||||||
BPX_O_ACCMODE = 0x03
|
|
||||||
BPX_O_GETFL = 0x0f
|
|
||||||
|
|
||||||
//mode
|
|
||||||
// byte1 (file type)
|
|
||||||
BPX_FT_DIR = 1
|
|
||||||
BPX_FT_CHARSPEC = 2
|
|
||||||
BPX_FT_REGFILE = 3
|
|
||||||
BPX_FT_FIFO = 4
|
|
||||||
BPX_FT_SYMLINK = 5
|
|
||||||
BPX_FT_SOCKET = 6
|
|
||||||
//byte3
|
|
||||||
BPX_S_ISUID = 0x08
|
|
||||||
BPX_S_ISGID = 0x04
|
|
||||||
BPX_S_ISVTX = 0x02
|
|
||||||
BPX_S_IRWXU1 = 0x01
|
|
||||||
BPX_S_IRUSR = 0x01
|
|
||||||
//byte4
|
|
||||||
BPX_S_IRWXU2 = 0xc0
|
|
||||||
BPX_S_IWUSR = 0x80
|
|
||||||
BPX_S_IXUSR = 0x40
|
|
||||||
BPX_S_IRWXG = 0x38
|
|
||||||
BPX_S_IRGRP = 0x20
|
|
||||||
BPX_S_IWGRP = 0x10
|
|
||||||
BPX_S_IXGRP = 0x08
|
|
||||||
BPX_S_IRWXOX = 0x07
|
|
||||||
BPX_S_IROTH = 0x04
|
|
||||||
BPX_S_IWOTH = 0x02
|
|
||||||
BPX_S_IXOTH = 0x01
|
|
||||||
|
|
||||||
CW_INTRPT = 1
|
|
||||||
CW_CONDVAR = 32
|
|
||||||
CW_TIMEOUT = 64
|
|
||||||
|
|
||||||
PGTHA_NEXT = 2
|
|
||||||
PGTHA_CURRENT = 1
|
|
||||||
PGTHA_FIRST = 0
|
|
||||||
PGTHA_LAST = 3
|
|
||||||
PGTHA_PROCESS = 0x80
|
|
||||||
PGTHA_CONTTY = 0x40
|
|
||||||
PGTHA_PATH = 0x20
|
|
||||||
PGTHA_COMMAND = 0x10
|
|
||||||
PGTHA_FILEDATA = 0x08
|
|
||||||
PGTHA_THREAD = 0x04
|
|
||||||
PGTHA_PTAG = 0x02
|
|
||||||
PGTHA_COMMANDLONG = 0x01
|
|
||||||
PGTHA_THREADFAST = 0x80
|
|
||||||
PGTHA_FILEPATH = 0x40
|
|
||||||
PGTHA_THDSIGMASK = 0x20
|
|
||||||
// thread quiece mode
|
|
||||||
QUIESCE_TERM int32 = 1
|
|
||||||
QUIESCE_FORCE int32 = 2
|
|
||||||
QUIESCE_QUERY int32 = 3
|
|
||||||
QUIESCE_FREEZE int32 = 4
|
|
||||||
QUIESCE_UNFREEZE int32 = 5
|
|
||||||
FREEZE_THIS_THREAD int32 = 6
|
|
||||||
FREEZE_EXIT int32 = 8
|
|
||||||
QUIESCE_SRB int32 = 9
|
|
||||||
)
|
|
||||||
|
|
||||||
type Pgtha struct {
|
|
||||||
Pid uint32 // 0
|
|
||||||
Tid0 uint32 // 4
|
|
||||||
Tid1 uint32
|
|
||||||
Accesspid byte // C
|
|
||||||
Accesstid byte // D
|
|
||||||
Accessasid uint16 // E
|
|
||||||
Loginname [8]byte // 10
|
|
||||||
Flag1 byte // 18
|
|
||||||
Flag1b2 byte // 19
|
|
||||||
}
|
|
||||||
|
|
||||||
type Bpxystat_t struct { // DSECT BPXYSTAT
|
|
||||||
St_id [4]uint8 // 0
|
|
||||||
St_length uint16 // 0x4
|
|
||||||
St_version uint16 // 0x6
|
|
||||||
St_mode uint32 // 0x8
|
|
||||||
St_ino uint32 // 0xc
|
|
||||||
St_dev uint32 // 0x10
|
|
||||||
St_nlink uint32 // 0x14
|
|
||||||
St_uid uint32 // 0x18
|
|
||||||
St_gid uint32 // 0x1c
|
|
||||||
St_size uint64 // 0x20
|
|
||||||
St_atime uint32 // 0x28
|
|
||||||
St_mtime uint32 // 0x2c
|
|
||||||
St_ctime uint32 // 0x30
|
|
||||||
St_rdev uint32 // 0x34
|
|
||||||
St_auditoraudit uint32 // 0x38
|
|
||||||
St_useraudit uint32 // 0x3c
|
|
||||||
St_blksize uint32 // 0x40
|
|
||||||
St_createtime uint32 // 0x44
|
|
||||||
St_auditid [4]uint32 // 0x48
|
|
||||||
St_res01 uint32 // 0x58
|
|
||||||
Ft_ccsid uint16 // 0x5c
|
|
||||||
Ft_flags uint16 // 0x5e
|
|
||||||
St_res01a [2]uint32 // 0x60
|
|
||||||
St_res02 uint32 // 0x68
|
|
||||||
St_blocks uint32 // 0x6c
|
|
||||||
St_opaque [3]uint8 // 0x70
|
|
||||||
St_visible uint8 // 0x73
|
|
||||||
St_reftime uint32 // 0x74
|
|
||||||
St_fid uint64 // 0x78
|
|
||||||
St_filefmt uint8 // 0x80
|
|
||||||
St_fspflag2 uint8 // 0x81
|
|
||||||
St_res03 [2]uint8 // 0x82
|
|
||||||
St_ctimemsec uint32 // 0x84
|
|
||||||
St_seclabel [8]uint8 // 0x88
|
|
||||||
St_res04 [4]uint8 // 0x90
|
|
||||||
// end of version 1
|
|
||||||
_ uint32 // 0x94
|
|
||||||
St_atime64 uint64 // 0x98
|
|
||||||
St_mtime64 uint64 // 0xa0
|
|
||||||
St_ctime64 uint64 // 0xa8
|
|
||||||
St_createtime64 uint64 // 0xb0
|
|
||||||
St_reftime64 uint64 // 0xb8
|
|
||||||
_ uint64 // 0xc0
|
|
||||||
St_res05 [16]uint8 // 0xc8
|
|
||||||
// end of version 2
|
|
||||||
}
|
|
||||||
|
|
||||||
type BpxFilestatus struct {
|
|
||||||
Oflag1 byte
|
|
||||||
Oflag2 byte
|
|
||||||
Oflag3 byte
|
|
||||||
Oflag4 byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type BpxMode struct {
|
|
||||||
Ftype byte
|
|
||||||
Mode1 byte
|
|
||||||
Mode2 byte
|
|
||||||
Mode3 byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thr attribute structure for extended attributes
|
|
||||||
type Bpxyatt_t struct { // DSECT BPXYATT
|
|
||||||
Att_id [4]uint8
|
|
||||||
Att_version uint16
|
|
||||||
Att_res01 [2]uint8
|
|
||||||
Att_setflags1 uint8
|
|
||||||
Att_setflags2 uint8
|
|
||||||
Att_setflags3 uint8
|
|
||||||
Att_setflags4 uint8
|
|
||||||
Att_mode uint32
|
|
||||||
Att_uid uint32
|
|
||||||
Att_gid uint32
|
|
||||||
Att_opaquemask [3]uint8
|
|
||||||
Att_visblmaskres uint8
|
|
||||||
Att_opaque [3]uint8
|
|
||||||
Att_visibleres uint8
|
|
||||||
Att_size_h uint32
|
|
||||||
Att_size_l uint32
|
|
||||||
Att_atime uint32
|
|
||||||
Att_mtime uint32
|
|
||||||
Att_auditoraudit uint32
|
|
||||||
Att_useraudit uint32
|
|
||||||
Att_ctime uint32
|
|
||||||
Att_reftime uint32
|
|
||||||
// end of version 1
|
|
||||||
Att_filefmt uint8
|
|
||||||
Att_res02 [3]uint8
|
|
||||||
Att_filetag uint32
|
|
||||||
Att_res03 [8]uint8
|
|
||||||
// end of version 2
|
|
||||||
Att_atime64 uint64
|
|
||||||
Att_mtime64 uint64
|
|
||||||
Att_ctime64 uint64
|
|
||||||
Att_reftime64 uint64
|
|
||||||
Att_seclabel [8]uint8
|
|
||||||
Att_ver3res02 [8]uint8
|
|
||||||
// end of version 3
|
|
||||||
}
|
|
||||||
|
|
||||||
func BpxOpen(name string, options *BpxFilestatus, mode *BpxMode) (rv int32, rc int32, rn int32) {
|
|
||||||
if len(name) < 1024 {
|
|
||||||
var namebuf [1024]byte
|
|
||||||
sz := int32(copy(namebuf[:], name))
|
|
||||||
A2e(namebuf[:sz])
|
|
||||||
var parms [7]unsafe.Pointer
|
|
||||||
parms[0] = unsafe.Pointer(&sz)
|
|
||||||
parms[1] = unsafe.Pointer(&namebuf[0])
|
|
||||||
parms[2] = unsafe.Pointer(options)
|
|
||||||
parms[3] = unsafe.Pointer(mode)
|
|
||||||
parms[4] = unsafe.Pointer(&rv)
|
|
||||||
parms[5] = unsafe.Pointer(&rc)
|
|
||||||
parms[6] = unsafe.Pointer(&rn)
|
|
||||||
bpxcall(parms[:], BPX4OPN)
|
|
||||||
return rv, rc, rn
|
|
||||||
}
|
|
||||||
return -1, -1, -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func BpxClose(fd int32) (rv int32, rc int32, rn int32) {
|
|
||||||
var parms [4]unsafe.Pointer
|
|
||||||
parms[0] = unsafe.Pointer(&fd)
|
|
||||||
parms[1] = unsafe.Pointer(&rv)
|
|
||||||
parms[2] = unsafe.Pointer(&rc)
|
|
||||||
parms[3] = unsafe.Pointer(&rn)
|
|
||||||
bpxcall(parms[:], BPX4CLO)
|
|
||||||
return rv, rc, rn
|
|
||||||
}
|
|
||||||
|
|
||||||
func BpxFileFStat(fd int32, st *Bpxystat_t) (rv int32, rc int32, rn int32) {
|
|
||||||
st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3}
|
|
||||||
st.St_version = 2
|
|
||||||
stat_sz := uint32(unsafe.Sizeof(*st))
|
|
||||||
var parms [6]unsafe.Pointer
|
|
||||||
parms[0] = unsafe.Pointer(&fd)
|
|
||||||
parms[1] = unsafe.Pointer(&stat_sz)
|
|
||||||
parms[2] = unsafe.Pointer(st)
|
|
||||||
parms[3] = unsafe.Pointer(&rv)
|
|
||||||
parms[4] = unsafe.Pointer(&rc)
|
|
||||||
parms[5] = unsafe.Pointer(&rn)
|
|
||||||
bpxcall(parms[:], BPX4FST)
|
|
||||||
return rv, rc, rn
|
|
||||||
}
|
|
||||||
|
|
||||||
func BpxFileStat(name string, st *Bpxystat_t) (rv int32, rc int32, rn int32) {
|
|
||||||
if len(name) < 1024 {
|
|
||||||
var namebuf [1024]byte
|
|
||||||
sz := int32(copy(namebuf[:], name))
|
|
||||||
A2e(namebuf[:sz])
|
|
||||||
st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3}
|
|
||||||
st.St_version = 2
|
|
||||||
stat_sz := uint32(unsafe.Sizeof(*st))
|
|
||||||
var parms [7]unsafe.Pointer
|
|
||||||
parms[0] = unsafe.Pointer(&sz)
|
|
||||||
parms[1] = unsafe.Pointer(&namebuf[0])
|
|
||||||
parms[2] = unsafe.Pointer(&stat_sz)
|
|
||||||
parms[3] = unsafe.Pointer(st)
|
|
||||||
parms[4] = unsafe.Pointer(&rv)
|
|
||||||
parms[5] = unsafe.Pointer(&rc)
|
|
||||||
parms[6] = unsafe.Pointer(&rn)
|
|
||||||
bpxcall(parms[:], BPX4STA)
|
|
||||||
return rv, rc, rn
|
|
||||||
}
|
|
||||||
return -1, -1, -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func BpxFileLStat(name string, st *Bpxystat_t) (rv int32, rc int32, rn int32) {
|
|
||||||
if len(name) < 1024 {
|
|
||||||
var namebuf [1024]byte
|
|
||||||
sz := int32(copy(namebuf[:], name))
|
|
||||||
A2e(namebuf[:sz])
|
|
||||||
st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3}
|
|
||||||
st.St_version = 2
|
|
||||||
stat_sz := uint32(unsafe.Sizeof(*st))
|
|
||||||
var parms [7]unsafe.Pointer
|
|
||||||
parms[0] = unsafe.Pointer(&sz)
|
|
||||||
parms[1] = unsafe.Pointer(&namebuf[0])
|
|
||||||
parms[2] = unsafe.Pointer(&stat_sz)
|
|
||||||
parms[3] = unsafe.Pointer(st)
|
|
||||||
parms[4] = unsafe.Pointer(&rv)
|
|
||||||
parms[5] = unsafe.Pointer(&rc)
|
|
||||||
parms[6] = unsafe.Pointer(&rn)
|
|
||||||
bpxcall(parms[:], BPX4LST)
|
|
||||||
return rv, rc, rn
|
|
||||||
}
|
|
||||||
return -1, -1, -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func BpxChattr(path string, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) {
|
|
||||||
if len(path) >= 1024 {
|
|
||||||
return -1, -1, -1
|
|
||||||
}
|
|
||||||
var namebuf [1024]byte
|
|
||||||
sz := int32(copy(namebuf[:], path))
|
|
||||||
A2e(namebuf[:sz])
|
|
||||||
attr_sz := uint32(unsafe.Sizeof(*attr))
|
|
||||||
var parms [7]unsafe.Pointer
|
|
||||||
parms[0] = unsafe.Pointer(&sz)
|
|
||||||
parms[1] = unsafe.Pointer(&namebuf[0])
|
|
||||||
parms[2] = unsafe.Pointer(&attr_sz)
|
|
||||||
parms[3] = unsafe.Pointer(attr)
|
|
||||||
parms[4] = unsafe.Pointer(&rv)
|
|
||||||
parms[5] = unsafe.Pointer(&rc)
|
|
||||||
parms[6] = unsafe.Pointer(&rn)
|
|
||||||
bpxcall(parms[:], BPX4CHR)
|
|
||||||
return rv, rc, rn
|
|
||||||
}
|
|
||||||
|
|
||||||
func BpxLchattr(path string, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) {
|
|
||||||
if len(path) >= 1024 {
|
|
||||||
return -1, -1, -1
|
|
||||||
}
|
|
||||||
var namebuf [1024]byte
|
|
||||||
sz := int32(copy(namebuf[:], path))
|
|
||||||
A2e(namebuf[:sz])
|
|
||||||
attr_sz := uint32(unsafe.Sizeof(*attr))
|
|
||||||
var parms [7]unsafe.Pointer
|
|
||||||
parms[0] = unsafe.Pointer(&sz)
|
|
||||||
parms[1] = unsafe.Pointer(&namebuf[0])
|
|
||||||
parms[2] = unsafe.Pointer(&attr_sz)
|
|
||||||
parms[3] = unsafe.Pointer(attr)
|
|
||||||
parms[4] = unsafe.Pointer(&rv)
|
|
||||||
parms[5] = unsafe.Pointer(&rc)
|
|
||||||
parms[6] = unsafe.Pointer(&rn)
|
|
||||||
bpxcall(parms[:], BPX4LCR)
|
|
||||||
return rv, rc, rn
|
|
||||||
}
|
|
||||||
|
|
||||||
func BpxFchattr(fd int32, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) {
|
|
||||||
attr_sz := uint32(unsafe.Sizeof(*attr))
|
|
||||||
var parms [6]unsafe.Pointer
|
|
||||||
parms[0] = unsafe.Pointer(&fd)
|
|
||||||
parms[1] = unsafe.Pointer(&attr_sz)
|
|
||||||
parms[2] = unsafe.Pointer(attr)
|
|
||||||
parms[3] = unsafe.Pointer(&rv)
|
|
||||||
parms[4] = unsafe.Pointer(&rc)
|
|
||||||
parms[5] = unsafe.Pointer(&rn)
|
|
||||||
bpxcall(parms[:], BPX4FCR)
|
|
||||||
return rv, rc, rn
|
|
||||||
}
|
|
||||||
|
|
||||||
func BpxCondTimedWait(sec uint32, nsec uint32, events uint32, secrem *uint32, nsecrem *uint32) (rv int32, rc int32, rn int32) {
|
|
||||||
var parms [8]unsafe.Pointer
|
|
||||||
parms[0] = unsafe.Pointer(&sec)
|
|
||||||
parms[1] = unsafe.Pointer(&nsec)
|
|
||||||
parms[2] = unsafe.Pointer(&events)
|
|
||||||
parms[3] = unsafe.Pointer(secrem)
|
|
||||||
parms[4] = unsafe.Pointer(nsecrem)
|
|
||||||
parms[5] = unsafe.Pointer(&rv)
|
|
||||||
parms[6] = unsafe.Pointer(&rc)
|
|
||||||
parms[7] = unsafe.Pointer(&rn)
|
|
||||||
bpxcall(parms[:], BPX4CTW)
|
|
||||||
return rv, rc, rn
|
|
||||||
}
|
|
||||||
func BpxGetthent(in *Pgtha, outlen *uint32, out unsafe.Pointer) (rv int32, rc int32, rn int32) {
|
|
||||||
var parms [7]unsafe.Pointer
|
|
||||||
inlen := uint32(26) // nothing else will work. Go says Pgtha is 28-byte because of alignment, but Pgtha is "packed" and must be 26-byte
|
|
||||||
parms[0] = unsafe.Pointer(&inlen)
|
|
||||||
parms[1] = unsafe.Pointer(&in)
|
|
||||||
parms[2] = unsafe.Pointer(outlen)
|
|
||||||
parms[3] = unsafe.Pointer(&out)
|
|
||||||
parms[4] = unsafe.Pointer(&rv)
|
|
||||||
parms[5] = unsafe.Pointer(&rc)
|
|
||||||
parms[6] = unsafe.Pointer(&rn)
|
|
||||||
bpxcall(parms[:], BPX4GTH)
|
|
||||||
return rv, rc, rn
|
|
||||||
}
|
|
||||||
func ZosJobname() (jobname string, err error) {
|
|
||||||
var pgtha Pgtha
|
|
||||||
pgtha.Pid = uint32(Getpid())
|
|
||||||
pgtha.Accesspid = PGTHA_CURRENT
|
|
||||||
pgtha.Flag1 = PGTHA_PROCESS
|
|
||||||
var out [256]byte
|
|
||||||
var outlen uint32
|
|
||||||
outlen = 256
|
|
||||||
rv, rc, rn := BpxGetthent(&pgtha, &outlen, unsafe.Pointer(&out[0]))
|
|
||||||
if rv == 0 {
|
|
||||||
gthc := []byte{0x87, 0xa3, 0x88, 0x83} // 'gthc' in ebcdic
|
|
||||||
ix := bytes.Index(out[:], gthc)
|
|
||||||
if ix == -1 {
|
|
||||||
err = fmt.Errorf("BPX4GTH: gthc return data not found")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
jn := out[ix+80 : ix+88] // we didn't declare Pgthc, but jobname is 8-byte at offset 80
|
|
||||||
E2a(jn)
|
|
||||||
jobname = string(bytes.TrimRight(jn, " "))
|
|
||||||
|
|
||||||
} else {
|
|
||||||
err = fmt.Errorf("BPX4GTH: rc=%d errno=%d reason=code=0x%x", rv, rc, rn)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func Bpx4ptq(code int32, data string) (rv int32, rc int32, rn int32) {
|
|
||||||
var userdata [8]byte
|
|
||||||
var parms [5]unsafe.Pointer
|
|
||||||
copy(userdata[:], data+" ")
|
|
||||||
A2e(userdata[:])
|
|
||||||
parms[0] = unsafe.Pointer(&code)
|
|
||||||
parms[1] = unsafe.Pointer(&userdata[0])
|
|
||||||
parms[2] = unsafe.Pointer(&rv)
|
|
||||||
parms[3] = unsafe.Pointer(&rc)
|
|
||||||
parms[4] = unsafe.Pointer(&rn)
|
|
||||||
bpxcall(parms[:], BPX4PTQ)
|
|
||||||
return rv, rc, rn
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
PT_TRACE_ME = 0 // Debug this process
|
|
||||||
PT_READ_I = 1 // Read a full word
|
|
||||||
PT_READ_D = 2 // Read a full word
|
|
||||||
PT_READ_U = 3 // Read control info
|
|
||||||
PT_WRITE_I = 4 //Write a full word
|
|
||||||
PT_WRITE_D = 5 //Write a full word
|
|
||||||
PT_CONTINUE = 7 //Continue the process
|
|
||||||
PT_KILL = 8 //Terminate the process
|
|
||||||
PT_READ_GPR = 11 // Read GPR, CR, PSW
|
|
||||||
PT_READ_FPR = 12 // Read FPR
|
|
||||||
PT_READ_VR = 13 // Read VR
|
|
||||||
PT_WRITE_GPR = 14 // Write GPR, CR, PSW
|
|
||||||
PT_WRITE_FPR = 15 // Write FPR
|
|
||||||
PT_WRITE_VR = 16 // Write VR
|
|
||||||
PT_READ_BLOCK = 17 // Read storage
|
|
||||||
PT_WRITE_BLOCK = 19 // Write storage
|
|
||||||
PT_READ_GPRH = 20 // Read GPRH
|
|
||||||
PT_WRITE_GPRH = 21 // Write GPRH
|
|
||||||
PT_REGHSET = 22 // Read all GPRHs
|
|
||||||
PT_ATTACH = 30 // Attach to a process
|
|
||||||
PT_DETACH = 31 // Detach from a process
|
|
||||||
PT_REGSET = 32 // Read all GPRs
|
|
||||||
PT_REATTACH = 33 // Reattach to a process
|
|
||||||
PT_LDINFO = 34 // Read loader info
|
|
||||||
PT_MULTI = 35 // Multi process mode
|
|
||||||
PT_LD64INFO = 36 // RMODE64 Info Area
|
|
||||||
PT_BLOCKREQ = 40 // Block request
|
|
||||||
PT_THREAD_INFO = 60 // Read thread info
|
|
||||||
PT_THREAD_MODIFY = 61
|
|
||||||
PT_THREAD_READ_FOCUS = 62
|
|
||||||
PT_THREAD_WRITE_FOCUS = 63
|
|
||||||
PT_THREAD_HOLD = 64
|
|
||||||
PT_THREAD_SIGNAL = 65
|
|
||||||
PT_EXPLAIN = 66
|
|
||||||
PT_EVENTS = 67
|
|
||||||
PT_THREAD_INFO_EXTENDED = 68
|
|
||||||
PT_REATTACH2 = 71
|
|
||||||
PT_CAPTURE = 72
|
|
||||||
PT_UNCAPTURE = 73
|
|
||||||
PT_GET_THREAD_TCB = 74
|
|
||||||
PT_GET_ALET = 75
|
|
||||||
PT_SWAPIN = 76
|
|
||||||
PT_EXTENDED_EVENT = 98
|
|
||||||
PT_RECOVER = 99 // Debug a program check
|
|
||||||
PT_GPR0 = 0 // General purpose register 0
|
|
||||||
PT_GPR1 = 1 // General purpose register 1
|
|
||||||
PT_GPR2 = 2 // General purpose register 2
|
|
||||||
PT_GPR3 = 3 // General purpose register 3
|
|
||||||
PT_GPR4 = 4 // General purpose register 4
|
|
||||||
PT_GPR5 = 5 // General purpose register 5
|
|
||||||
PT_GPR6 = 6 // General purpose register 6
|
|
||||||
PT_GPR7 = 7 // General purpose register 7
|
|
||||||
PT_GPR8 = 8 // General purpose register 8
|
|
||||||
PT_GPR9 = 9 // General purpose register 9
|
|
||||||
PT_GPR10 = 10 // General purpose register 10
|
|
||||||
PT_GPR11 = 11 // General purpose register 11
|
|
||||||
PT_GPR12 = 12 // General purpose register 12
|
|
||||||
PT_GPR13 = 13 // General purpose register 13
|
|
||||||
PT_GPR14 = 14 // General purpose register 14
|
|
||||||
PT_GPR15 = 15 // General purpose register 15
|
|
||||||
PT_FPR0 = 16 // Floating point register 0
|
|
||||||
PT_FPR1 = 17 // Floating point register 1
|
|
||||||
PT_FPR2 = 18 // Floating point register 2
|
|
||||||
PT_FPR3 = 19 // Floating point register 3
|
|
||||||
PT_FPR4 = 20 // Floating point register 4
|
|
||||||
PT_FPR5 = 21 // Floating point register 5
|
|
||||||
PT_FPR6 = 22 // Floating point register 6
|
|
||||||
PT_FPR7 = 23 // Floating point register 7
|
|
||||||
PT_FPR8 = 24 // Floating point register 8
|
|
||||||
PT_FPR9 = 25 // Floating point register 9
|
|
||||||
PT_FPR10 = 26 // Floating point register 10
|
|
||||||
PT_FPR11 = 27 // Floating point register 11
|
|
||||||
PT_FPR12 = 28 // Floating point register 12
|
|
||||||
PT_FPR13 = 29 // Floating point register 13
|
|
||||||
PT_FPR14 = 30 // Floating point register 14
|
|
||||||
PT_FPR15 = 31 // Floating point register 15
|
|
||||||
PT_FPC = 32 // Floating point control register
|
|
||||||
PT_PSW = 40 // PSW
|
|
||||||
PT_PSW0 = 40 // Left half of the PSW
|
|
||||||
PT_PSW1 = 41 // Right half of the PSW
|
|
||||||
PT_CR0 = 42 // Control register 0
|
|
||||||
PT_CR1 = 43 // Control register 1
|
|
||||||
PT_CR2 = 44 // Control register 2
|
|
||||||
PT_CR3 = 45 // Control register 3
|
|
||||||
PT_CR4 = 46 // Control register 4
|
|
||||||
PT_CR5 = 47 // Control register 5
|
|
||||||
PT_CR6 = 48 // Control register 6
|
|
||||||
PT_CR7 = 49 // Control register 7
|
|
||||||
PT_CR8 = 50 // Control register 8
|
|
||||||
PT_CR9 = 51 // Control register 9
|
|
||||||
PT_CR10 = 52 // Control register 10
|
|
||||||
PT_CR11 = 53 // Control register 11
|
|
||||||
PT_CR12 = 54 // Control register 12
|
|
||||||
PT_CR13 = 55 // Control register 13
|
|
||||||
PT_CR14 = 56 // Control register 14
|
|
||||||
PT_CR15 = 57 // Control register 15
|
|
||||||
PT_GPRH0 = 58 // GP High register 0
|
|
||||||
PT_GPRH1 = 59 // GP High register 1
|
|
||||||
PT_GPRH2 = 60 // GP High register 2
|
|
||||||
PT_GPRH3 = 61 // GP High register 3
|
|
||||||
PT_GPRH4 = 62 // GP High register 4
|
|
||||||
PT_GPRH5 = 63 // GP High register 5
|
|
||||||
PT_GPRH6 = 64 // GP High register 6
|
|
||||||
PT_GPRH7 = 65 // GP High register 7
|
|
||||||
PT_GPRH8 = 66 // GP High register 8
|
|
||||||
PT_GPRH9 = 67 // GP High register 9
|
|
||||||
PT_GPRH10 = 68 // GP High register 10
|
|
||||||
PT_GPRH11 = 69 // GP High register 11
|
|
||||||
PT_GPRH12 = 70 // GP High register 12
|
|
||||||
PT_GPRH13 = 71 // GP High register 13
|
|
||||||
PT_GPRH14 = 72 // GP High register 14
|
|
||||||
PT_GPRH15 = 73 // GP High register 15
|
|
||||||
PT_VR0 = 74 // Vector register 0
|
|
||||||
PT_VR1 = 75 // Vector register 1
|
|
||||||
PT_VR2 = 76 // Vector register 2
|
|
||||||
PT_VR3 = 77 // Vector register 3
|
|
||||||
PT_VR4 = 78 // Vector register 4
|
|
||||||
PT_VR5 = 79 // Vector register 5
|
|
||||||
PT_VR6 = 80 // Vector register 6
|
|
||||||
PT_VR7 = 81 // Vector register 7
|
|
||||||
PT_VR8 = 82 // Vector register 8
|
|
||||||
PT_VR9 = 83 // Vector register 9
|
|
||||||
PT_VR10 = 84 // Vector register 10
|
|
||||||
PT_VR11 = 85 // Vector register 11
|
|
||||||
PT_VR12 = 86 // Vector register 12
|
|
||||||
PT_VR13 = 87 // Vector register 13
|
|
||||||
PT_VR14 = 88 // Vector register 14
|
|
||||||
PT_VR15 = 89 // Vector register 15
|
|
||||||
PT_VR16 = 90 // Vector register 16
|
|
||||||
PT_VR17 = 91 // Vector register 17
|
|
||||||
PT_VR18 = 92 // Vector register 18
|
|
||||||
PT_VR19 = 93 // Vector register 19
|
|
||||||
PT_VR20 = 94 // Vector register 20
|
|
||||||
PT_VR21 = 95 // Vector register 21
|
|
||||||
PT_VR22 = 96 // Vector register 22
|
|
||||||
PT_VR23 = 97 // Vector register 23
|
|
||||||
PT_VR24 = 98 // Vector register 24
|
|
||||||
PT_VR25 = 99 // Vector register 25
|
|
||||||
PT_VR26 = 100 // Vector register 26
|
|
||||||
PT_VR27 = 101 // Vector register 27
|
|
||||||
PT_VR28 = 102 // Vector register 28
|
|
||||||
PT_VR29 = 103 // Vector register 29
|
|
||||||
PT_VR30 = 104 // Vector register 30
|
|
||||||
PT_VR31 = 105 // Vector register 31
|
|
||||||
PT_PSWG = 106 // PSWG
|
|
||||||
PT_PSWG0 = 106 // Bytes 0-3
|
|
||||||
PT_PSWG1 = 107 // Bytes 4-7
|
|
||||||
PT_PSWG2 = 108 // Bytes 8-11 (IA high word)
|
|
||||||
PT_PSWG3 = 109 // Bytes 12-15 (IA low word)
|
|
||||||
)
|
|
||||||
|
|
||||||
func Bpx4ptr(request int32, pid int32, addr unsafe.Pointer, data unsafe.Pointer, buffer unsafe.Pointer) (rv int32, rc int32, rn int32) {
|
|
||||||
var parms [8]unsafe.Pointer
|
|
||||||
parms[0] = unsafe.Pointer(&request)
|
|
||||||
parms[1] = unsafe.Pointer(&pid)
|
|
||||||
parms[2] = unsafe.Pointer(&addr)
|
|
||||||
parms[3] = unsafe.Pointer(&data)
|
|
||||||
parms[4] = unsafe.Pointer(&buffer)
|
|
||||||
parms[5] = unsafe.Pointer(&rv)
|
|
||||||
parms[6] = unsafe.Pointer(&rc)
|
|
||||||
parms[7] = unsafe.Pointer(&rn)
|
|
||||||
bpxcall(parms[:], BPX4PTR)
|
|
||||||
return rv, rc, rn
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyU8(val uint8, dest []uint8) int {
|
|
||||||
if len(dest) < 1 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
dest[0] = val
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyU8Arr(src, dest []uint8) int {
|
|
||||||
if len(dest) < len(src) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
for i, v := range src {
|
|
||||||
dest[i] = v
|
|
||||||
}
|
|
||||||
return len(src)
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyU16(val uint16, dest []uint16) int {
|
|
||||||
if len(dest) < 1 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
dest[0] = val
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyU32(val uint32, dest []uint32) int {
|
|
||||||
if len(dest) < 1 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
dest[0] = val
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyU32Arr(src, dest []uint32) int {
|
|
||||||
if len(dest) < len(src) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
for i, v := range src {
|
|
||||||
dest[i] = v
|
|
||||||
}
|
|
||||||
return len(src)
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyU64(val uint64, dest []uint64) int {
|
|
||||||
if len(dest) < 1 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
dest[0] = val
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
192
vendor/golang.org/x/sys/unix/bpxsvc_zos.s
generated
vendored
192
vendor/golang.org/x/sys/unix/bpxsvc_zos.s
generated
vendored
@@ -1,192 +0,0 @@
|
|||||||
// Copyright 2024 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
#include "go_asm.h"
|
|
||||||
#include "textflag.h"
|
|
||||||
|
|
||||||
// function to call USS assembly language services
|
|
||||||
//
|
|
||||||
// doc: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_3.1.0/com.ibm.zos.v3r1.bpxb100/bit64env.htm
|
|
||||||
//
|
|
||||||
// arg1 unsafe.Pointer array that ressembles an OS PLIST
|
|
||||||
//
|
|
||||||
// arg2 function offset as in
|
|
||||||
// doc: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_3.1.0/com.ibm.zos.v3r1.bpxb100/bpx2cr_List_of_offsets.htm
|
|
||||||
//
|
|
||||||
// func bpxcall(plist []unsafe.Pointer, bpx_offset int64)
|
|
||||||
|
|
||||||
TEXT ·bpxcall(SB), NOSPLIT|NOFRAME, $0
|
|
||||||
MOVD plist_base+0(FP), R1 // r1 points to plist
|
|
||||||
MOVD bpx_offset+24(FP), R2 // r2 offset to BPX vector table
|
|
||||||
MOVD R14, R7 // save r14
|
|
||||||
MOVD R15, R8 // save r15
|
|
||||||
MOVWZ 16(R0), R9
|
|
||||||
MOVWZ 544(R9), R9
|
|
||||||
MOVWZ 24(R9), R9 // call vector in r9
|
|
||||||
ADD R2, R9 // add offset to vector table
|
|
||||||
MOVWZ (R9), R9 // r9 points to entry point
|
|
||||||
BYTE $0x0D // BL R14,R9 --> basr r14,r9
|
|
||||||
BYTE $0xE9 // clobbers 0,1,14,15
|
|
||||||
MOVD R8, R15 // restore 15
|
|
||||||
JMP R7 // return via saved return address
|
|
||||||
|
|
||||||
// func A2e(arr [] byte)
|
|
||||||
// code page conversion from 819 to 1047
|
|
||||||
TEXT ·A2e(SB), NOSPLIT|NOFRAME, $0
|
|
||||||
MOVD arg_base+0(FP), R2 // pointer to arry of characters
|
|
||||||
MOVD arg_len+8(FP), R3 // count
|
|
||||||
XOR R0, R0
|
|
||||||
XOR R1, R1
|
|
||||||
BYTE $0xA7; BYTE $0x15; BYTE $0x00; BYTE $0x82 // BRAS 1,(2+(256/2))
|
|
||||||
|
|
||||||
// ASCII -> EBCDIC conversion table:
|
|
||||||
BYTE $0x00; BYTE $0x01; BYTE $0x02; BYTE $0x03
|
|
||||||
BYTE $0x37; BYTE $0x2d; BYTE $0x2e; BYTE $0x2f
|
|
||||||
BYTE $0x16; BYTE $0x05; BYTE $0x15; BYTE $0x0b
|
|
||||||
BYTE $0x0c; BYTE $0x0d; BYTE $0x0e; BYTE $0x0f
|
|
||||||
BYTE $0x10; BYTE $0x11; BYTE $0x12; BYTE $0x13
|
|
||||||
BYTE $0x3c; BYTE $0x3d; BYTE $0x32; BYTE $0x26
|
|
||||||
BYTE $0x18; BYTE $0x19; BYTE $0x3f; BYTE $0x27
|
|
||||||
BYTE $0x1c; BYTE $0x1d; BYTE $0x1e; BYTE $0x1f
|
|
||||||
BYTE $0x40; BYTE $0x5a; BYTE $0x7f; BYTE $0x7b
|
|
||||||
BYTE $0x5b; BYTE $0x6c; BYTE $0x50; BYTE $0x7d
|
|
||||||
BYTE $0x4d; BYTE $0x5d; BYTE $0x5c; BYTE $0x4e
|
|
||||||
BYTE $0x6b; BYTE $0x60; BYTE $0x4b; BYTE $0x61
|
|
||||||
BYTE $0xf0; BYTE $0xf1; BYTE $0xf2; BYTE $0xf3
|
|
||||||
BYTE $0xf4; BYTE $0xf5; BYTE $0xf6; BYTE $0xf7
|
|
||||||
BYTE $0xf8; BYTE $0xf9; BYTE $0x7a; BYTE $0x5e
|
|
||||||
BYTE $0x4c; BYTE $0x7e; BYTE $0x6e; BYTE $0x6f
|
|
||||||
BYTE $0x7c; BYTE $0xc1; BYTE $0xc2; BYTE $0xc3
|
|
||||||
BYTE $0xc4; BYTE $0xc5; BYTE $0xc6; BYTE $0xc7
|
|
||||||
BYTE $0xc8; BYTE $0xc9; BYTE $0xd1; BYTE $0xd2
|
|
||||||
BYTE $0xd3; BYTE $0xd4; BYTE $0xd5; BYTE $0xd6
|
|
||||||
BYTE $0xd7; BYTE $0xd8; BYTE $0xd9; BYTE $0xe2
|
|
||||||
BYTE $0xe3; BYTE $0xe4; BYTE $0xe5; BYTE $0xe6
|
|
||||||
BYTE $0xe7; BYTE $0xe8; BYTE $0xe9; BYTE $0xad
|
|
||||||
BYTE $0xe0; BYTE $0xbd; BYTE $0x5f; BYTE $0x6d
|
|
||||||
BYTE $0x79; BYTE $0x81; BYTE $0x82; BYTE $0x83
|
|
||||||
BYTE $0x84; BYTE $0x85; BYTE $0x86; BYTE $0x87
|
|
||||||
BYTE $0x88; BYTE $0x89; BYTE $0x91; BYTE $0x92
|
|
||||||
BYTE $0x93; BYTE $0x94; BYTE $0x95; BYTE $0x96
|
|
||||||
BYTE $0x97; BYTE $0x98; BYTE $0x99; BYTE $0xa2
|
|
||||||
BYTE $0xa3; BYTE $0xa4; BYTE $0xa5; BYTE $0xa6
|
|
||||||
BYTE $0xa7; BYTE $0xa8; BYTE $0xa9; BYTE $0xc0
|
|
||||||
BYTE $0x4f; BYTE $0xd0; BYTE $0xa1; BYTE $0x07
|
|
||||||
BYTE $0x20; BYTE $0x21; BYTE $0x22; BYTE $0x23
|
|
||||||
BYTE $0x24; BYTE $0x25; BYTE $0x06; BYTE $0x17
|
|
||||||
BYTE $0x28; BYTE $0x29; BYTE $0x2a; BYTE $0x2b
|
|
||||||
BYTE $0x2c; BYTE $0x09; BYTE $0x0a; BYTE $0x1b
|
|
||||||
BYTE $0x30; BYTE $0x31; BYTE $0x1a; BYTE $0x33
|
|
||||||
BYTE $0x34; BYTE $0x35; BYTE $0x36; BYTE $0x08
|
|
||||||
BYTE $0x38; BYTE $0x39; BYTE $0x3a; BYTE $0x3b
|
|
||||||
BYTE $0x04; BYTE $0x14; BYTE $0x3e; BYTE $0xff
|
|
||||||
BYTE $0x41; BYTE $0xaa; BYTE $0x4a; BYTE $0xb1
|
|
||||||
BYTE $0x9f; BYTE $0xb2; BYTE $0x6a; BYTE $0xb5
|
|
||||||
BYTE $0xbb; BYTE $0xb4; BYTE $0x9a; BYTE $0x8a
|
|
||||||
BYTE $0xb0; BYTE $0xca; BYTE $0xaf; BYTE $0xbc
|
|
||||||
BYTE $0x90; BYTE $0x8f; BYTE $0xea; BYTE $0xfa
|
|
||||||
BYTE $0xbe; BYTE $0xa0; BYTE $0xb6; BYTE $0xb3
|
|
||||||
BYTE $0x9d; BYTE $0xda; BYTE $0x9b; BYTE $0x8b
|
|
||||||
BYTE $0xb7; BYTE $0xb8; BYTE $0xb9; BYTE $0xab
|
|
||||||
BYTE $0x64; BYTE $0x65; BYTE $0x62; BYTE $0x66
|
|
||||||
BYTE $0x63; BYTE $0x67; BYTE $0x9e; BYTE $0x68
|
|
||||||
BYTE $0x74; BYTE $0x71; BYTE $0x72; BYTE $0x73
|
|
||||||
BYTE $0x78; BYTE $0x75; BYTE $0x76; BYTE $0x77
|
|
||||||
BYTE $0xac; BYTE $0x69; BYTE $0xed; BYTE $0xee
|
|
||||||
BYTE $0xeb; BYTE $0xef; BYTE $0xec; BYTE $0xbf
|
|
||||||
BYTE $0x80; BYTE $0xfd; BYTE $0xfe; BYTE $0xfb
|
|
||||||
BYTE $0xfc; BYTE $0xba; BYTE $0xae; BYTE $0x59
|
|
||||||
BYTE $0x44; BYTE $0x45; BYTE $0x42; BYTE $0x46
|
|
||||||
BYTE $0x43; BYTE $0x47; BYTE $0x9c; BYTE $0x48
|
|
||||||
BYTE $0x54; BYTE $0x51; BYTE $0x52; BYTE $0x53
|
|
||||||
BYTE $0x58; BYTE $0x55; BYTE $0x56; BYTE $0x57
|
|
||||||
BYTE $0x8c; BYTE $0x49; BYTE $0xcd; BYTE $0xce
|
|
||||||
BYTE $0xcb; BYTE $0xcf; BYTE $0xcc; BYTE $0xe1
|
|
||||||
BYTE $0x70; BYTE $0xdd; BYTE $0xde; BYTE $0xdb
|
|
||||||
BYTE $0xdc; BYTE $0x8d; BYTE $0x8e; BYTE $0xdf
|
|
||||||
|
|
||||||
retry:
|
|
||||||
WORD $0xB9931022 // TROO 2,2,b'0001'
|
|
||||||
BVS retry
|
|
||||||
RET
|
|
||||||
|
|
||||||
// func e2a(arr [] byte)
|
|
||||||
// code page conversion from 1047 to 819
|
|
||||||
TEXT ·E2a(SB), NOSPLIT|NOFRAME, $0
|
|
||||||
MOVD arg_base+0(FP), R2 // pointer to arry of characters
|
|
||||||
MOVD arg_len+8(FP), R3 // count
|
|
||||||
XOR R0, R0
|
|
||||||
XOR R1, R1
|
|
||||||
BYTE $0xA7; BYTE $0x15; BYTE $0x00; BYTE $0x82 // BRAS 1,(2+(256/2))
|
|
||||||
|
|
||||||
// EBCDIC -> ASCII conversion table:
|
|
||||||
BYTE $0x00; BYTE $0x01; BYTE $0x02; BYTE $0x03
|
|
||||||
BYTE $0x9c; BYTE $0x09; BYTE $0x86; BYTE $0x7f
|
|
||||||
BYTE $0x97; BYTE $0x8d; BYTE $0x8e; BYTE $0x0b
|
|
||||||
BYTE $0x0c; BYTE $0x0d; BYTE $0x0e; BYTE $0x0f
|
|
||||||
BYTE $0x10; BYTE $0x11; BYTE $0x12; BYTE $0x13
|
|
||||||
BYTE $0x9d; BYTE $0x0a; BYTE $0x08; BYTE $0x87
|
|
||||||
BYTE $0x18; BYTE $0x19; BYTE $0x92; BYTE $0x8f
|
|
||||||
BYTE $0x1c; BYTE $0x1d; BYTE $0x1e; BYTE $0x1f
|
|
||||||
BYTE $0x80; BYTE $0x81; BYTE $0x82; BYTE $0x83
|
|
||||||
BYTE $0x84; BYTE $0x85; BYTE $0x17; BYTE $0x1b
|
|
||||||
BYTE $0x88; BYTE $0x89; BYTE $0x8a; BYTE $0x8b
|
|
||||||
BYTE $0x8c; BYTE $0x05; BYTE $0x06; BYTE $0x07
|
|
||||||
BYTE $0x90; BYTE $0x91; BYTE $0x16; BYTE $0x93
|
|
||||||
BYTE $0x94; BYTE $0x95; BYTE $0x96; BYTE $0x04
|
|
||||||
BYTE $0x98; BYTE $0x99; BYTE $0x9a; BYTE $0x9b
|
|
||||||
BYTE $0x14; BYTE $0x15; BYTE $0x9e; BYTE $0x1a
|
|
||||||
BYTE $0x20; BYTE $0xa0; BYTE $0xe2; BYTE $0xe4
|
|
||||||
BYTE $0xe0; BYTE $0xe1; BYTE $0xe3; BYTE $0xe5
|
|
||||||
BYTE $0xe7; BYTE $0xf1; BYTE $0xa2; BYTE $0x2e
|
|
||||||
BYTE $0x3c; BYTE $0x28; BYTE $0x2b; BYTE $0x7c
|
|
||||||
BYTE $0x26; BYTE $0xe9; BYTE $0xea; BYTE $0xeb
|
|
||||||
BYTE $0xe8; BYTE $0xed; BYTE $0xee; BYTE $0xef
|
|
||||||
BYTE $0xec; BYTE $0xdf; BYTE $0x21; BYTE $0x24
|
|
||||||
BYTE $0x2a; BYTE $0x29; BYTE $0x3b; BYTE $0x5e
|
|
||||||
BYTE $0x2d; BYTE $0x2f; BYTE $0xc2; BYTE $0xc4
|
|
||||||
BYTE $0xc0; BYTE $0xc1; BYTE $0xc3; BYTE $0xc5
|
|
||||||
BYTE $0xc7; BYTE $0xd1; BYTE $0xa6; BYTE $0x2c
|
|
||||||
BYTE $0x25; BYTE $0x5f; BYTE $0x3e; BYTE $0x3f
|
|
||||||
BYTE $0xf8; BYTE $0xc9; BYTE $0xca; BYTE $0xcb
|
|
||||||
BYTE $0xc8; BYTE $0xcd; BYTE $0xce; BYTE $0xcf
|
|
||||||
BYTE $0xcc; BYTE $0x60; BYTE $0x3a; BYTE $0x23
|
|
||||||
BYTE $0x40; BYTE $0x27; BYTE $0x3d; BYTE $0x22
|
|
||||||
BYTE $0xd8; BYTE $0x61; BYTE $0x62; BYTE $0x63
|
|
||||||
BYTE $0x64; BYTE $0x65; BYTE $0x66; BYTE $0x67
|
|
||||||
BYTE $0x68; BYTE $0x69; BYTE $0xab; BYTE $0xbb
|
|
||||||
BYTE $0xf0; BYTE $0xfd; BYTE $0xfe; BYTE $0xb1
|
|
||||||
BYTE $0xb0; BYTE $0x6a; BYTE $0x6b; BYTE $0x6c
|
|
||||||
BYTE $0x6d; BYTE $0x6e; BYTE $0x6f; BYTE $0x70
|
|
||||||
BYTE $0x71; BYTE $0x72; BYTE $0xaa; BYTE $0xba
|
|
||||||
BYTE $0xe6; BYTE $0xb8; BYTE $0xc6; BYTE $0xa4
|
|
||||||
BYTE $0xb5; BYTE $0x7e; BYTE $0x73; BYTE $0x74
|
|
||||||
BYTE $0x75; BYTE $0x76; BYTE $0x77; BYTE $0x78
|
|
||||||
BYTE $0x79; BYTE $0x7a; BYTE $0xa1; BYTE $0xbf
|
|
||||||
BYTE $0xd0; BYTE $0x5b; BYTE $0xde; BYTE $0xae
|
|
||||||
BYTE $0xac; BYTE $0xa3; BYTE $0xa5; BYTE $0xb7
|
|
||||||
BYTE $0xa9; BYTE $0xa7; BYTE $0xb6; BYTE $0xbc
|
|
||||||
BYTE $0xbd; BYTE $0xbe; BYTE $0xdd; BYTE $0xa8
|
|
||||||
BYTE $0xaf; BYTE $0x5d; BYTE $0xb4; BYTE $0xd7
|
|
||||||
BYTE $0x7b; BYTE $0x41; BYTE $0x42; BYTE $0x43
|
|
||||||
BYTE $0x44; BYTE $0x45; BYTE $0x46; BYTE $0x47
|
|
||||||
BYTE $0x48; BYTE $0x49; BYTE $0xad; BYTE $0xf4
|
|
||||||
BYTE $0xf6; BYTE $0xf2; BYTE $0xf3; BYTE $0xf5
|
|
||||||
BYTE $0x7d; BYTE $0x4a; BYTE $0x4b; BYTE $0x4c
|
|
||||||
BYTE $0x4d; BYTE $0x4e; BYTE $0x4f; BYTE $0x50
|
|
||||||
BYTE $0x51; BYTE $0x52; BYTE $0xb9; BYTE $0xfb
|
|
||||||
BYTE $0xfc; BYTE $0xf9; BYTE $0xfa; BYTE $0xff
|
|
||||||
BYTE $0x5c; BYTE $0xf7; BYTE $0x53; BYTE $0x54
|
|
||||||
BYTE $0x55; BYTE $0x56; BYTE $0x57; BYTE $0x58
|
|
||||||
BYTE $0x59; BYTE $0x5a; BYTE $0xb2; BYTE $0xd4
|
|
||||||
BYTE $0xd6; BYTE $0xd2; BYTE $0xd3; BYTE $0xd5
|
|
||||||
BYTE $0x30; BYTE $0x31; BYTE $0x32; BYTE $0x33
|
|
||||||
BYTE $0x34; BYTE $0x35; BYTE $0x36; BYTE $0x37
|
|
||||||
BYTE $0x38; BYTE $0x39; BYTE $0xb3; BYTE $0xdb
|
|
||||||
BYTE $0xdc; BYTE $0xd9; BYTE $0xda; BYTE $0x9f
|
|
||||||
|
|
||||||
retry:
|
|
||||||
WORD $0xB9931022 // TROO 2,2,b'0001'
|
|
||||||
BVS retry
|
|
||||||
RET
|
|
||||||
1
vendor/golang.org/x/sys/unix/cap_freebsd.go
generated
vendored
1
vendor/golang.org/x/sys/unix/cap_freebsd.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build freebsd
|
//go:build freebsd
|
||||||
|
// +build freebsd
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/constants.go
generated
vendored
1
vendor/golang.org/x/sys/unix/constants.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// 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 || zos
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/dev_aix_ppc.go
generated
vendored
1
vendor/golang.org/x/sys/unix/dev_aix_ppc.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix && ppc
|
//go:build aix && ppc
|
||||||
|
// +build aix,ppc
|
||||||
|
|
||||||
// Functions to access/create device major and minor numbers matching the
|
// Functions to access/create device major and minor numbers matching the
|
||||||
// encoding used by AIX.
|
// encoding used by AIX.
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/dev_aix_ppc64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/dev_aix_ppc64.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix && ppc64
|
//go:build aix && ppc64
|
||||||
|
// +build aix,ppc64
|
||||||
|
|
||||||
// Functions to access/create device major and minor numbers matching the
|
// Functions to access/create device major and minor numbers matching the
|
||||||
// encoding used AIX.
|
// encoding used AIX.
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/dev_zos.go
generated
vendored
1
vendor/golang.org/x/sys/unix/dev_zos.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build zos && s390x
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
// Functions to access/create device major and minor numbers matching the
|
// Functions to access/create device major and minor numbers matching the
|
||||||
// encoding used by z/OS.
|
// encoding used by z/OS.
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/dirent.go
generated
vendored
1
vendor/golang.org/x/sys/unix/dirent.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// 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 || zos
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/endian_big.go
generated
vendored
1
vendor/golang.org/x/sys/unix/endian_big.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
//
|
//
|
||||||
//go:build armbe || arm64be || m68k || mips || mips64 || mips64p32 || ppc || ppc64 || s390 || s390x || shbe || sparc || sparc64
|
//go:build armbe || arm64be || m68k || mips || mips64 || mips64p32 || ppc || ppc64 || s390 || s390x || shbe || sparc || sparc64
|
||||||
|
// +build armbe arm64be m68k mips mips64 mips64p32 ppc ppc64 s390 s390x shbe sparc sparc64
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/endian_little.go
generated
vendored
1
vendor/golang.org/x/sys/unix/endian_little.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// 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 || loong64 || 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 loong64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/env_unix.go
generated
vendored
1
vendor/golang.org/x/sys/unix/env_unix.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// 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 || zos
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
// Unix environment variables.
|
// Unix environment variables.
|
||||||
|
|
||||||
|
|||||||
221
vendor/golang.org/x/sys/unix/epoll_zos.go
generated
vendored
Normal file
221
vendor/golang.org/x/sys/unix/epoll_zos.go
generated
vendored
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This file simulates epoll on z/OS using poll.
|
||||||
|
|
||||||
|
// Analogous to epoll_event on Linux.
|
||||||
|
// TODO(neeilan): Pad is because the Linux kernel expects a 96-bit struct. We never pass this to the kernel; remove?
|
||||||
|
type EpollEvent struct {
|
||||||
|
Events uint32
|
||||||
|
Fd int32
|
||||||
|
Pad int32
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
EPOLLERR = 0x8
|
||||||
|
EPOLLHUP = 0x10
|
||||||
|
EPOLLIN = 0x1
|
||||||
|
EPOLLMSG = 0x400
|
||||||
|
EPOLLOUT = 0x4
|
||||||
|
EPOLLPRI = 0x2
|
||||||
|
EPOLLRDBAND = 0x80
|
||||||
|
EPOLLRDNORM = 0x40
|
||||||
|
EPOLLWRBAND = 0x200
|
||||||
|
EPOLLWRNORM = 0x100
|
||||||
|
EPOLL_CTL_ADD = 0x1
|
||||||
|
EPOLL_CTL_DEL = 0x2
|
||||||
|
EPOLL_CTL_MOD = 0x3
|
||||||
|
// The following constants are part of the epoll API, but represent
|
||||||
|
// currently unsupported functionality on z/OS.
|
||||||
|
// EPOLL_CLOEXEC = 0x80000
|
||||||
|
// EPOLLET = 0x80000000
|
||||||
|
// EPOLLONESHOT = 0x40000000
|
||||||
|
// EPOLLRDHUP = 0x2000 // Typically used with edge-triggered notis
|
||||||
|
// EPOLLEXCLUSIVE = 0x10000000 // Exclusive wake-up mode
|
||||||
|
// EPOLLWAKEUP = 0x20000000 // Relies on Linux's BLOCK_SUSPEND capability
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(neeilan): We can eliminate these epToPoll / pToEpoll calls by using identical mask values for POLL/EPOLL
|
||||||
|
// constants where possible The lower 16 bits of epoll events (uint32) can fit any system poll event (int16).
|
||||||
|
|
||||||
|
// epToPollEvt converts epoll event field to poll equivalent.
|
||||||
|
// In epoll, Events is a 32-bit field, while poll uses 16 bits.
|
||||||
|
func epToPollEvt(events uint32) int16 {
|
||||||
|
var ep2p = map[uint32]int16{
|
||||||
|
EPOLLIN: POLLIN,
|
||||||
|
EPOLLOUT: POLLOUT,
|
||||||
|
EPOLLHUP: POLLHUP,
|
||||||
|
EPOLLPRI: POLLPRI,
|
||||||
|
EPOLLERR: POLLERR,
|
||||||
|
}
|
||||||
|
|
||||||
|
var pollEvts int16 = 0
|
||||||
|
for epEvt, pEvt := range ep2p {
|
||||||
|
if (events & epEvt) != 0 {
|
||||||
|
pollEvts |= pEvt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pollEvts
|
||||||
|
}
|
||||||
|
|
||||||
|
// pToEpollEvt converts 16 bit poll event bitfields to 32-bit epoll event fields.
|
||||||
|
func pToEpollEvt(revents int16) uint32 {
|
||||||
|
var p2ep = map[int16]uint32{
|
||||||
|
POLLIN: EPOLLIN,
|
||||||
|
POLLOUT: EPOLLOUT,
|
||||||
|
POLLHUP: EPOLLHUP,
|
||||||
|
POLLPRI: EPOLLPRI,
|
||||||
|
POLLERR: EPOLLERR,
|
||||||
|
}
|
||||||
|
|
||||||
|
var epollEvts uint32 = 0
|
||||||
|
for pEvt, epEvt := range p2ep {
|
||||||
|
if (revents & pEvt) != 0 {
|
||||||
|
epollEvts |= epEvt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return epollEvts
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per-process epoll implementation.
|
||||||
|
type epollImpl struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
epfd2ep map[int]*eventPoll
|
||||||
|
nextEpfd int
|
||||||
|
}
|
||||||
|
|
||||||
|
// eventPoll holds a set of file descriptors being watched by the process. A process can have multiple epoll instances.
|
||||||
|
// On Linux, this is an in-kernel data structure accessed through a fd.
|
||||||
|
type eventPoll struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
fds map[int]*EpollEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
// epoll impl for this process.
|
||||||
|
var impl epollImpl = epollImpl{
|
||||||
|
epfd2ep: make(map[int]*eventPoll),
|
||||||
|
nextEpfd: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *epollImpl) epollcreate(size int) (epfd int, err error) {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
epfd = e.nextEpfd
|
||||||
|
e.nextEpfd++
|
||||||
|
|
||||||
|
e.epfd2ep[epfd] = &eventPoll{
|
||||||
|
fds: make(map[int]*EpollEvent),
|
||||||
|
}
|
||||||
|
return epfd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *epollImpl) epollcreate1(flag int) (fd int, err error) {
|
||||||
|
return e.epollcreate(4)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *epollImpl) epollctl(epfd int, op int, fd int, event *EpollEvent) (err error) {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
|
||||||
|
ep, ok := e.epfd2ep[epfd]
|
||||||
|
if !ok {
|
||||||
|
|
||||||
|
return EBADF
|
||||||
|
}
|
||||||
|
|
||||||
|
switch op {
|
||||||
|
case EPOLL_CTL_ADD:
|
||||||
|
// TODO(neeilan): When we make epfds and fds disjoint, detect epoll
|
||||||
|
// loops here (instances watching each other) and return ELOOP.
|
||||||
|
if _, ok := ep.fds[fd]; ok {
|
||||||
|
return EEXIST
|
||||||
|
}
|
||||||
|
ep.fds[fd] = event
|
||||||
|
case EPOLL_CTL_MOD:
|
||||||
|
if _, ok := ep.fds[fd]; !ok {
|
||||||
|
return ENOENT
|
||||||
|
}
|
||||||
|
ep.fds[fd] = event
|
||||||
|
case EPOLL_CTL_DEL:
|
||||||
|
if _, ok := ep.fds[fd]; !ok {
|
||||||
|
return ENOENT
|
||||||
|
}
|
||||||
|
delete(ep.fds, fd)
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must be called while holding ep.mu
|
||||||
|
func (ep *eventPoll) getFds() []int {
|
||||||
|
fds := make([]int, len(ep.fds))
|
||||||
|
for fd := range ep.fds {
|
||||||
|
fds = append(fds, fd)
|
||||||
|
}
|
||||||
|
return fds
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *epollImpl) epollwait(epfd int, events []EpollEvent, msec int) (n int, err error) {
|
||||||
|
e.mu.Lock() // in [rare] case of concurrent epollcreate + epollwait
|
||||||
|
ep, ok := e.epfd2ep[epfd]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
e.mu.Unlock()
|
||||||
|
return 0, EBADF
|
||||||
|
}
|
||||||
|
|
||||||
|
pollfds := make([]PollFd, 4)
|
||||||
|
for fd, epollevt := range ep.fds {
|
||||||
|
pollfds = append(pollfds, PollFd{Fd: int32(fd), Events: epToPollEvt(epollevt.Events)})
|
||||||
|
}
|
||||||
|
e.mu.Unlock()
|
||||||
|
|
||||||
|
n, err = Poll(pollfds, msec)
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for _, pFd := range pollfds {
|
||||||
|
if pFd.Revents != 0 {
|
||||||
|
events[i] = EpollEvent{Fd: pFd.Fd, Events: pToEpollEvt(pFd.Revents)}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
if i == n {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func EpollCreate(size int) (fd int, err error) {
|
||||||
|
return impl.epollcreate(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func EpollCreate1(flag int) (fd int, err error) {
|
||||||
|
return impl.epollcreate1(flag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
|
||||||
|
return impl.epollctl(epfd, op, fd, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because EpollWait mutates events, the caller is expected to coordinate
|
||||||
|
// concurrent access if calling with the same epfd from multiple goroutines.
|
||||||
|
func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
|
||||||
|
return impl.epollwait(epfd, events, msec)
|
||||||
|
}
|
||||||
3
vendor/golang.org/x/sys/unix/fcntl.go
generated
vendored
3
vendor/golang.org/x/sys/unix/fcntl.go
generated
vendored
@@ -2,7 +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 dragonfly || freebsd || linux || netbsd
|
//go:build dragonfly || freebsd || linux || netbsd || openbsd
|
||||||
|
// +build dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go
generated
vendored
1
vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (linux && 386) || (linux && arm) || (linux && mips) || (linux && mipsle) || (linux && ppc)
|
//go:build (linux && 386) || (linux && arm) || (linux && mips) || (linux && mipsle) || (linux && ppc)
|
||||||
|
// +build linux,386 linux,arm linux,mips linux,mipsle linux,ppc
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/fdset.go
generated
vendored
1
vendor/golang.org/x/sys/unix/fdset.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// 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 || zos
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
164
vendor/golang.org/x/sys/unix/fstatfs_zos.go
generated
vendored
Normal file
164
vendor/golang.org/x/sys/unix/fstatfs_zos.go
generated
vendored
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This file simulates fstatfs on z/OS using fstatvfs and w_getmntent.
|
||||||
|
|
||||||
|
func Fstatfs(fd int, stat *Statfs_t) (err error) {
|
||||||
|
var stat_v Statvfs_t
|
||||||
|
err = Fstatvfs(fd, &stat_v)
|
||||||
|
if err == nil {
|
||||||
|
// populate stat
|
||||||
|
stat.Type = 0
|
||||||
|
stat.Bsize = stat_v.Bsize
|
||||||
|
stat.Blocks = stat_v.Blocks
|
||||||
|
stat.Bfree = stat_v.Bfree
|
||||||
|
stat.Bavail = stat_v.Bavail
|
||||||
|
stat.Files = stat_v.Files
|
||||||
|
stat.Ffree = stat_v.Ffree
|
||||||
|
stat.Fsid = stat_v.Fsid
|
||||||
|
stat.Namelen = stat_v.Namemax
|
||||||
|
stat.Frsize = stat_v.Frsize
|
||||||
|
stat.Flags = stat_v.Flag
|
||||||
|
for passn := 0; passn < 5; passn++ {
|
||||||
|
switch passn {
|
||||||
|
case 0:
|
||||||
|
err = tryGetmntent64(stat)
|
||||||
|
break
|
||||||
|
case 1:
|
||||||
|
err = tryGetmntent128(stat)
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
err = tryGetmntent256(stat)
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
err = tryGetmntent512(stat)
|
||||||
|
break
|
||||||
|
case 4:
|
||||||
|
err = tryGetmntent1024(stat)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
//proceed to return if: err is nil (found), err is nonnil but not ERANGE (another error occurred)
|
||||||
|
if err == nil || err != nil && err != ERANGE {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent64(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [64]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent128(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [128]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent256(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [256]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent512(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [512]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent1024(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [1024]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
1
vendor/golang.org/x/sys/unix/gccgo.go
generated
vendored
1
vendor/golang.org/x/sys/unix/gccgo.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gccgo && !aix && !hurd
|
//go:build gccgo && !aix && !hurd
|
||||||
|
// +build gccgo,!aix,!hurd
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
1
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gccgo && !aix && !hurd
|
//go:build gccgo && !aix && !hurd
|
||||||
|
// +build gccgo,!aix,!hurd
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gccgo && linux && amd64
|
//go:build gccgo && linux && amd64
|
||||||
|
// +build gccgo,linux,amd64
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/ifreq_linux.go
generated
vendored
1
vendor/golang.org/x/sys/unix/ifreq_linux.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build linux
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
5
vendor/golang.org/x/sys/unix/ioctl_linux.go
generated
vendored
5
vendor/golang.org/x/sys/unix/ioctl_linux.go
generated
vendored
@@ -231,8 +231,3 @@ func IoctlLoopGetStatus64(fd int) (*LoopInfo64, error) {
|
|||||||
func IoctlLoopSetStatus64(fd int, value *LoopInfo64) error {
|
func IoctlLoopSetStatus64(fd int, value *LoopInfo64) error {
|
||||||
return ioctlPtr(fd, LOOP_SET_STATUS64, unsafe.Pointer(value))
|
return ioctlPtr(fd, LOOP_SET_STATUS64, unsafe.Pointer(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IoctlLoopConfigure configures all loop device parameters in a single step
|
|
||||||
func IoctlLoopConfigure(fd int, value *LoopConfig) error {
|
|
||||||
return ioctlPtr(fd, LOOP_CONFIGURE, unsafe.Pointer(value))
|
|
||||||
}
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/ioctl_signed.go
generated
vendored
1
vendor/golang.org/x/sys/unix/ioctl_signed.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || solaris
|
//go:build aix || solaris
|
||||||
|
// +build aix solaris
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/ioctl_unsigned.go
generated
vendored
1
vendor/golang.org/x/sys/unix/ioctl_unsigned.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd
|
//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd
|
||||||
|
// +build darwin dragonfly freebsd hurd linux netbsd openbsd
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/ioctl_zos.go
generated
vendored
1
vendor/golang.org/x/sys/unix/ioctl_zos.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build zos && s390x
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
50
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
50
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
@@ -248,7 +248,6 @@ struct ltchars {
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
#include <linux/netfilter/nfnetlink.h>
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
#include <linux/netfilter/nf_tables.h>
|
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/net_namespace.h>
|
#include <linux/net_namespace.h>
|
||||||
#include <linux/nfc.h>
|
#include <linux/nfc.h>
|
||||||
@@ -263,7 +262,6 @@ struct ltchars {
|
|||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/seccomp.h>
|
#include <linux/seccomp.h>
|
||||||
#include <linux/serial.h>
|
#include <linux/serial.h>
|
||||||
#include <linux/sock_diag.h>
|
|
||||||
#include <linux/sockios.h>
|
#include <linux/sockios.h>
|
||||||
#include <linux/taskstats.h>
|
#include <linux/taskstats.h>
|
||||||
#include <linux/tipc.h>
|
#include <linux/tipc.h>
|
||||||
@@ -285,6 +283,10 @@ struct ltchars {
|
|||||||
#include <asm/termbits.h>
|
#include <asm/termbits.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MSG_FASTOPEN
|
||||||
|
#define MSG_FASTOPEN 0x20000000
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef PTRACE_GETREGS
|
#ifndef PTRACE_GETREGS
|
||||||
#define PTRACE_GETREGS 0xc
|
#define PTRACE_GETREGS 0xc
|
||||||
#endif
|
#endif
|
||||||
@@ -293,6 +295,14 @@ struct ltchars {
|
|||||||
#define PTRACE_SETREGS 0xd
|
#define PTRACE_SETREGS 0xd
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SOL_NETLINK
|
||||||
|
#define SOL_NETLINK 270
|
||||||
|
#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
|
||||||
@@ -309,23 +319,10 @@ struct ltchars {
|
|||||||
#undef TIPC_WAIT_FOREVER
|
#undef TIPC_WAIT_FOREVER
|
||||||
#define TIPC_WAIT_FOREVER 0xffffffff
|
#define TIPC_WAIT_FOREVER 0xffffffff
|
||||||
|
|
||||||
// Copied from linux/netfilter/nf_nat.h
|
// Copied from linux/l2tp.h
|
||||||
// Including linux/netfilter/nf_nat.h here causes conflicts between linux/in.h
|
// Including linux/l2tp.h here causes conflicts between linux/in.h
|
||||||
// and netinet/in.h.
|
// and netinet/in.h included via net/route.h above.
|
||||||
#define NF_NAT_RANGE_MAP_IPS (1 << 0)
|
#define IPPROTO_L2TP 115
|
||||||
#define NF_NAT_RANGE_PROTO_SPECIFIED (1 << 1)
|
|
||||||
#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2)
|
|
||||||
#define NF_NAT_RANGE_PERSISTENT (1 << 3)
|
|
||||||
#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4)
|
|
||||||
#define NF_NAT_RANGE_PROTO_OFFSET (1 << 5)
|
|
||||||
#define NF_NAT_RANGE_NETMAP (1 << 6)
|
|
||||||
#define NF_NAT_RANGE_PROTO_RANDOM_ALL \
|
|
||||||
(NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY)
|
|
||||||
#define NF_NAT_RANGE_MASK \
|
|
||||||
(NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | \
|
|
||||||
NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | \
|
|
||||||
NF_NAT_RANGE_PROTO_RANDOM_FULLY | NF_NAT_RANGE_PROTO_OFFSET | \
|
|
||||||
NF_NAT_RANGE_NETMAP)
|
|
||||||
|
|
||||||
// Copied from linux/hid.h.
|
// Copied from linux/hid.h.
|
||||||
// Keep in sync with the size of the referenced fields.
|
// Keep in sync with the size of the referenced fields.
|
||||||
@@ -522,8 +519,7 @@ ccflags="$@"
|
|||||||
$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 == "LOOP_CONFIGURE" ||
|
$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|UDP)_/ ||
|
||||||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MREMAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ ||
|
|
||||||
$2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ ||
|
$2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ ||
|
||||||
$2 ~ /^NFC_.*_(MAX)?SIZE$/ ||
|
$2 ~ /^NFC_.*_(MAX)?SIZE$/ ||
|
||||||
$2 ~ /^RAW_PAYLOAD_/ ||
|
$2 ~ /^RAW_PAYLOAD_/ ||
|
||||||
@@ -550,7 +546,6 @@ ccflags="$@"
|
|||||||
$2 !~ "NLA_TYPE_MASK" &&
|
$2 !~ "NLA_TYPE_MASK" &&
|
||||||
$2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ &&
|
$2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ &&
|
||||||
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
|
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
|
||||||
$2 ~ /^SOCK_|SK_DIAG_|SKNLGRP_$/ ||
|
|
||||||
$2 ~ /^FIORDCHK$/ ||
|
$2 ~ /^FIORDCHK$/ ||
|
||||||
$2 ~ /^SIOC/ ||
|
$2 ~ /^SIOC/ ||
|
||||||
$2 ~ /^TIOC/ ||
|
$2 ~ /^TIOC/ ||
|
||||||
@@ -565,7 +560,7 @@ ccflags="$@"
|
|||||||
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
|
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
|
||||||
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
|
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
|
||||||
$2 ~ /^CLONE_[A-Z_]+/ ||
|
$2 ~ /^CLONE_[A-Z_]+/ ||
|
||||||
$2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+|BPF_F_LINK)$/ &&
|
$2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+)$/ &&
|
||||||
$2 ~ /^(BPF|DLT)_/ ||
|
$2 ~ /^(BPF|DLT)_/ ||
|
||||||
$2 ~ /^AUDIT_/ ||
|
$2 ~ /^AUDIT_/ ||
|
||||||
$2 ~ /^(CLOCK|TIMER)_/ ||
|
$2 ~ /^(CLOCK|TIMER)_/ ||
|
||||||
@@ -586,9 +581,8 @@ ccflags="$@"
|
|||||||
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
|
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
|
||||||
$2 ~ /^KEYCTL_/ ||
|
$2 ~ /^KEYCTL_/ ||
|
||||||
$2 ~ /^PERF_/ ||
|
$2 ~ /^PERF_/ ||
|
||||||
$2 ~ /^SECCOMP_/ ||
|
$2 ~ /^SECCOMP_MODE_/ ||
|
||||||
$2 ~ /^SEEK_/ ||
|
$2 ~ /^SEEK_/ ||
|
||||||
$2 ~ /^SCHED_/ ||
|
|
||||||
$2 ~ /^SPLICE_/ ||
|
$2 ~ /^SPLICE_/ ||
|
||||||
$2 ~ /^SYNC_FILE_RANGE_/ ||
|
$2 ~ /^SYNC_FILE_RANGE_/ ||
|
||||||
$2 !~ /IOC_MAGIC/ &&
|
$2 !~ /IOC_MAGIC/ &&
|
||||||
@@ -607,9 +601,6 @@ ccflags="$@"
|
|||||||
$2 ~ /^FSOPT_/ ||
|
$2 ~ /^FSOPT_/ ||
|
||||||
$2 ~ /^WDIO[CFS]_/ ||
|
$2 ~ /^WDIO[CFS]_/ ||
|
||||||
$2 ~ /^NFN/ ||
|
$2 ~ /^NFN/ ||
|
||||||
$2 !~ /^NFT_META_IIFTYPE/ &&
|
|
||||||
$2 ~ /^NFT_/ ||
|
|
||||||
$2 ~ /^NF_NAT_/ ||
|
|
||||||
$2 ~ /^XDP_/ ||
|
$2 ~ /^XDP_/ ||
|
||||||
$2 ~ /^RWF_/ ||
|
$2 ~ /^RWF_/ ||
|
||||||
$2 ~ /^(HDIO|WIN|SMART)_/ ||
|
$2 ~ /^(HDIO|WIN|SMART)_/ ||
|
||||||
@@ -633,7 +624,7 @@ ccflags="$@"
|
|||||||
$2 ~ /^MEM/ ||
|
$2 ~ /^MEM/ ||
|
||||||
$2 ~ /^WG/ ||
|
$2 ~ /^WG/ ||
|
||||||
$2 ~ /^FIB_RULE_/ ||
|
$2 ~ /^FIB_RULE_/ ||
|
||||||
$2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE|IOMIN$|IOOPT$|ALIGNOFF$|DISCARD|ROTATIONAL$|ZEROOUT$|GETDISKSEQ$)/ {printf("\t%s = C.%s\n", $2, $2)}
|
$2 ~ /^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)}
|
||||||
|
|
||||||
@@ -671,6 +662,7 @@ echo '// mkerrors.sh' "$@"
|
|||||||
echo '// Code generated by the command above; see README.md. DO NOT EDIT.'
|
echo '// Code generated by the command above; see README.md. DO NOT EDIT.'
|
||||||
echo
|
echo
|
||||||
echo "//go:build ${GOARCH} && ${GOOS}"
|
echo "//go:build ${GOARCH} && ${GOOS}"
|
||||||
|
echo "// +build ${GOARCH},${GOOS}"
|
||||||
echo
|
echo
|
||||||
go tool cgo -godefs -- "$@" _const.go >_error.out
|
go tool cgo -godefs -- "$@" _const.go >_error.out
|
||||||
cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
|
cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
|
||||||
|
|||||||
13
vendor/golang.org/x/sys/unix/mmap_nomremap.go
generated
vendored
13
vendor/golang.org/x/sys/unix/mmap_nomremap.go
generated
vendored
@@ -1,13 +0,0 @@
|
|||||||
// Copyright 2023 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris || zos
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
var mapper = &mmapper{
|
|
||||||
active: make(map[*byte][]byte),
|
|
||||||
mmap: mmap,
|
|
||||||
munmap: munmap,
|
|
||||||
}
|
|
||||||
57
vendor/golang.org/x/sys/unix/mremap.go
generated
vendored
57
vendor/golang.org/x/sys/unix/mremap.go
generated
vendored
@@ -1,57 +0,0 @@
|
|||||||
// Copyright 2023 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build linux || netbsd
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
type mremapMmapper struct {
|
|
||||||
mmapper
|
|
||||||
mremap func(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
var mapper = &mremapMmapper{
|
|
||||||
mmapper: mmapper{
|
|
||||||
active: make(map[*byte][]byte),
|
|
||||||
mmap: mmap,
|
|
||||||
munmap: munmap,
|
|
||||||
},
|
|
||||||
mremap: mremap,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mremapMmapper) Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) {
|
|
||||||
if newLength <= 0 || len(oldData) == 0 || len(oldData) != cap(oldData) || flags&mremapFixed != 0 {
|
|
||||||
return nil, EINVAL
|
|
||||||
}
|
|
||||||
|
|
||||||
pOld := &oldData[cap(oldData)-1]
|
|
||||||
m.Lock()
|
|
||||||
defer m.Unlock()
|
|
||||||
bOld := m.active[pOld]
|
|
||||||
if bOld == nil || &bOld[0] != &oldData[0] {
|
|
||||||
return nil, EINVAL
|
|
||||||
}
|
|
||||||
newAddr, errno := m.mremap(uintptr(unsafe.Pointer(&bOld[0])), uintptr(len(bOld)), uintptr(newLength), flags, 0)
|
|
||||||
if errno != nil {
|
|
||||||
return nil, errno
|
|
||||||
}
|
|
||||||
bNew := unsafe.Slice((*byte)(unsafe.Pointer(newAddr)), newLength)
|
|
||||||
pNew := &bNew[cap(bNew)-1]
|
|
||||||
if flags&mremapDontunmap == 0 {
|
|
||||||
delete(m.active, pOld)
|
|
||||||
}
|
|
||||||
m.active[pNew] = bNew
|
|
||||||
return bNew, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) {
|
|
||||||
return mapper.Mremap(oldData, newLength, flags)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MremapPtr(oldAddr unsafe.Pointer, oldSize uintptr, newAddr unsafe.Pointer, newSize uintptr, flags int) (ret unsafe.Pointer, err error) {
|
|
||||||
xaddr, err := mapper.mremap(uintptr(oldAddr), oldSize, newSize, flags, uintptr(newAddr))
|
|
||||||
return unsafe.Pointer(xaddr), err
|
|
||||||
}
|
|
||||||
3
vendor/golang.org/x/sys/unix/pagesize_unix.go
generated
vendored
3
vendor/golang.org/x/sys/unix/pagesize_unix.go
generated
vendored
@@ -2,7 +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 || zos
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
// For Unix, get the pagesize from the runtime.
|
// For Unix, get the pagesize from the runtime.
|
||||||
|
|
||||||
|
|||||||
110
vendor/golang.org/x/sys/unix/pledge_openbsd.go
generated
vendored
110
vendor/golang.org/x/sys/unix/pledge_openbsd.go
generated
vendored
@@ -8,31 +8,54 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Pledge implements the pledge syscall.
|
// Pledge implements the pledge syscall.
|
||||||
//
|
//
|
||||||
// This changes both the promises and execpromises; use PledgePromises or
|
// The pledge syscall does not accept execpromises on OpenBSD releases
|
||||||
// PledgeExecpromises to only change the promises or execpromises
|
// before 6.3.
|
||||||
// respectively.
|
//
|
||||||
|
// execpromises must be empty when Pledge is called on OpenBSD
|
||||||
|
// releases predating 6.3, otherwise an error will be returned.
|
||||||
//
|
//
|
||||||
// For more information see pledge(2).
|
// For more information see pledge(2).
|
||||||
func Pledge(promises, execpromises string) error {
|
func Pledge(promises, execpromises string) error {
|
||||||
if err := pledgeAvailable(); err != nil {
|
maj, min, err := majmin()
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
pptr, err := BytePtrFromString(promises)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
exptr, err := BytePtrFromString(execpromises)
|
err = pledgeAvailable(maj, min, execpromises)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return pledge(pptr, exptr)
|
pptr, err := syscall.BytePtrFromString(promises)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// This variable will hold either a nil unsafe.Pointer or
|
||||||
|
// an unsafe.Pointer to a string (execpromises).
|
||||||
|
var expr unsafe.Pointer
|
||||||
|
|
||||||
|
// If we're running on OpenBSD > 6.2, pass execpromises to the syscall.
|
||||||
|
if maj > 6 || (maj == 6 && min > 2) {
|
||||||
|
exptr, err := syscall.BytePtrFromString(execpromises)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
expr = unsafe.Pointer(exptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0)
|
||||||
|
if e != 0 {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PledgePromises implements the pledge syscall.
|
// PledgePromises implements the pledge syscall.
|
||||||
@@ -41,16 +64,30 @@ func Pledge(promises, execpromises string) error {
|
|||||||
//
|
//
|
||||||
// For more information see pledge(2).
|
// For more information see pledge(2).
|
||||||
func PledgePromises(promises string) error {
|
func PledgePromises(promises string) error {
|
||||||
if err := pledgeAvailable(); err != nil {
|
maj, min, err := majmin()
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
pptr, err := BytePtrFromString(promises)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return pledge(pptr, nil)
|
err = pledgeAvailable(maj, min, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// This variable holds the execpromises and is always nil.
|
||||||
|
var expr unsafe.Pointer
|
||||||
|
|
||||||
|
pptr, err := syscall.BytePtrFromString(promises)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0)
|
||||||
|
if e != 0 {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PledgeExecpromises implements the pledge syscall.
|
// PledgeExecpromises implements the pledge syscall.
|
||||||
@@ -59,16 +96,30 @@ func PledgePromises(promises string) error {
|
|||||||
//
|
//
|
||||||
// For more information see pledge(2).
|
// For more information see pledge(2).
|
||||||
func PledgeExecpromises(execpromises string) error {
|
func PledgeExecpromises(execpromises string) error {
|
||||||
if err := pledgeAvailable(); err != nil {
|
maj, min, err := majmin()
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
exptr, err := BytePtrFromString(execpromises)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return pledge(nil, exptr)
|
err = pledgeAvailable(maj, min, execpromises)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// This variable holds the promises and is always nil.
|
||||||
|
var pptr unsafe.Pointer
|
||||||
|
|
||||||
|
exptr, err := syscall.BytePtrFromString(execpromises)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(pptr), uintptr(unsafe.Pointer(exptr)), 0)
|
||||||
|
if e != 0 {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// majmin returns major and minor version number for an OpenBSD system.
|
// majmin returns major and minor version number for an OpenBSD system.
|
||||||
@@ -96,15 +147,16 @@ func majmin() (major int, minor int, err error) {
|
|||||||
|
|
||||||
// pledgeAvailable checks for availability of the pledge(2) syscall
|
// pledgeAvailable checks for availability of the pledge(2) syscall
|
||||||
// based on the running OpenBSD version.
|
// based on the running OpenBSD version.
|
||||||
func pledgeAvailable() error {
|
func pledgeAvailable(maj, min int, execpromises string) error {
|
||||||
maj, min, err := majmin()
|
// If OpenBSD <= 5.9, pledge is not available.
|
||||||
if err != nil {
|
if (maj == 5 && min != 9) || maj < 5 {
|
||||||
return err
|
return fmt.Errorf("pledge syscall is not available on OpenBSD %d.%d", maj, min)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Require OpenBSD 6.4 as a minimum.
|
// If OpenBSD <= 6.2 and execpromises is not empty,
|
||||||
if maj < 6 || (maj == 6 && min <= 3) {
|
// return an error - execpromises is not available before 6.3
|
||||||
return fmt.Errorf("cannot call Pledge on OpenBSD %d.%d", maj, min)
|
if (maj < 6 || (maj == 6 && min <= 2)) && execpromises != "" {
|
||||||
|
return fmt.Errorf("cannot use execpromises on OpenBSD %d.%d", maj, min)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
7
vendor/golang.org/x/sys/unix/ptrace_darwin.go
generated
vendored
7
vendor/golang.org/x/sys/unix/ptrace_darwin.go
generated
vendored
@@ -3,9 +3,16 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build darwin && !ios
|
//go:build darwin && !ios
|
||||||
|
// +build darwin,!ios
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
func ptrace(request int, pid int, addr uintptr, data uintptr) error {
|
func ptrace(request int, pid int, addr uintptr, data uintptr) error {
|
||||||
return ptrace1(request, pid, addr, data)
|
return ptrace1(request, pid, addr, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ptracePtr(request int, pid int, addr uintptr, data unsafe.Pointer) error {
|
||||||
|
return ptrace1Ptr(request, pid, addr, data)
|
||||||
|
}
|
||||||
|
|||||||
7
vendor/golang.org/x/sys/unix/ptrace_ios.go
generated
vendored
7
vendor/golang.org/x/sys/unix/ptrace_ios.go
generated
vendored
@@ -3,9 +3,16 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build ios
|
//go:build ios
|
||||||
|
// +build ios
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
|
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
|
||||||
return ENOTSUP
|
return ENOTSUP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ptracePtr(request int, pid int, addr uintptr, data unsafe.Pointer) (err error) {
|
||||||
|
return ENOTSUP
|
||||||
|
}
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/race.go
generated
vendored
1
vendor/golang.org/x/sys/unix/race.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (darwin && race) || (linux && race) || (freebsd && race)
|
//go:build (darwin && race) || (linux && race) || (freebsd && race)
|
||||||
|
// +build darwin,race linux,race freebsd,race
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/race0.go
generated
vendored
1
vendor/golang.org/x/sys/unix/race0.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || (darwin && !race) || (linux && !race) || (freebsd && !race) || netbsd || openbsd || solaris || dragonfly || zos
|
//go:build aix || (darwin && !race) || (linux && !race) || (freebsd && !race) || netbsd || openbsd || solaris || dragonfly || zos
|
||||||
|
// +build aix darwin,!race linux,!race freebsd,!race netbsd openbsd solaris dragonfly zos
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/readdirent_getdents.go
generated
vendored
1
vendor/golang.org/x/sys/unix/readdirent_getdents.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || dragonfly || freebsd || linux || netbsd || openbsd
|
//go:build aix || dragonfly || freebsd || linux || netbsd || openbsd
|
||||||
|
// +build aix dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
3
vendor/golang.org/x/sys/unix/readdirent_getdirentries.go
generated
vendored
3
vendor/golang.org/x/sys/unix/readdirent_getdirentries.go
generated
vendored
@@ -2,7 +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 darwin || zos
|
//go:build darwin
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/sockcmsg_unix.go
generated
vendored
1
vendor/golang.org/x/sys/unix/sockcmsg_unix.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// 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 || zos
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
// Socket control messages
|
// Socket control messages
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go
generated
vendored
1
vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || darwin || freebsd || linux || netbsd || openbsd || solaris || zos
|
//go:build aix || darwin || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
|
// +build aix darwin freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
58
vendor/golang.org/x/sys/unix/sockcmsg_zos.go
generated
vendored
58
vendor/golang.org/x/sys/unix/sockcmsg_zos.go
generated
vendored
@@ -1,58 +0,0 @@
|
|||||||
// Copyright 2024 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Socket control messages
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
// UnixCredentials encodes credentials into a socket control message
|
|
||||||
// for sending to another process. This can be used for
|
|
||||||
// authentication.
|
|
||||||
func UnixCredentials(ucred *Ucred) []byte {
|
|
||||||
b := make([]byte, CmsgSpace(SizeofUcred))
|
|
||||||
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
|
|
||||||
h.Level = SOL_SOCKET
|
|
||||||
h.Type = SCM_CREDENTIALS
|
|
||||||
h.SetLen(CmsgLen(SizeofUcred))
|
|
||||||
*(*Ucred)(h.data(0)) = *ucred
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseUnixCredentials decodes a socket control message that contains
|
|
||||||
// credentials in a Ucred structure. To receive such a message, the
|
|
||||||
// SO_PASSCRED option must be enabled on the socket.
|
|
||||||
func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) {
|
|
||||||
if m.Header.Level != SOL_SOCKET {
|
|
||||||
return nil, EINVAL
|
|
||||||
}
|
|
||||||
if m.Header.Type != SCM_CREDENTIALS {
|
|
||||||
return nil, EINVAL
|
|
||||||
}
|
|
||||||
ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0]))
|
|
||||||
return &ucred, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PktInfo4 encodes Inet4Pktinfo into a socket control message of type IP_PKTINFO.
|
|
||||||
func PktInfo4(info *Inet4Pktinfo) []byte {
|
|
||||||
b := make([]byte, CmsgSpace(SizeofInet4Pktinfo))
|
|
||||||
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
|
|
||||||
h.Level = SOL_IP
|
|
||||||
h.Type = IP_PKTINFO
|
|
||||||
h.SetLen(CmsgLen(SizeofInet4Pktinfo))
|
|
||||||
*(*Inet4Pktinfo)(h.data(0)) = *info
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// PktInfo6 encodes Inet6Pktinfo into a socket control message of type IPV6_PKTINFO.
|
|
||||||
func PktInfo6(info *Inet6Pktinfo) []byte {
|
|
||||||
b := make([]byte, CmsgSpace(SizeofInet6Pktinfo))
|
|
||||||
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
|
|
||||||
h.Level = SOL_IPV6
|
|
||||||
h.Type = IPV6_PKTINFO
|
|
||||||
h.SetLen(CmsgLen(SizeofInet6Pktinfo))
|
|
||||||
*(*Inet6Pktinfo)(h.data(0)) = *info
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
75
vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s
generated
vendored
75
vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s
generated
vendored
@@ -1,75 +0,0 @@
|
|||||||
// Copyright 2024 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build zos && s390x && gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
|
||||||
|
|
||||||
// provide the address of function variable to be fixed up.
|
|
||||||
|
|
||||||
TEXT ·getPipe2Addr(SB), NOSPLIT|NOFRAME, $0-8
|
|
||||||
MOVD $·Pipe2(SB), R8
|
|
||||||
MOVD R8, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·get_FlockAddr(SB), NOSPLIT|NOFRAME, $0-8
|
|
||||||
MOVD $·Flock(SB), R8
|
|
||||||
MOVD R8, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·get_GetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
|
|
||||||
MOVD $·Getxattr(SB), R8
|
|
||||||
MOVD R8, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·get_NanosleepAddr(SB), NOSPLIT|NOFRAME, $0-8
|
|
||||||
MOVD $·Nanosleep(SB), R8
|
|
||||||
MOVD R8, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·get_SetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8
|
|
||||||
MOVD $·Setxattr(SB), R8
|
|
||||||
MOVD R8, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·get_Wait4Addr(SB), NOSPLIT|NOFRAME, $0-8
|
|
||||||
MOVD $·Wait4(SB), R8
|
|
||||||
MOVD R8, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·get_MountAddr(SB), NOSPLIT|NOFRAME, $0-8
|
|
||||||
MOVD $·Mount(SB), R8
|
|
||||||
MOVD R8, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·get_UnmountAddr(SB), NOSPLIT|NOFRAME, $0-8
|
|
||||||
MOVD $·Unmount(SB), R8
|
|
||||||
MOVD R8, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·get_UtimesNanoAtAddr(SB), NOSPLIT|NOFRAME, $0-8
|
|
||||||
MOVD $·UtimesNanoAt(SB), R8
|
|
||||||
MOVD R8, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·get_UtimesNanoAddr(SB), NOSPLIT|NOFRAME, $0-8
|
|
||||||
MOVD $·UtimesNano(SB), R8
|
|
||||||
MOVD R8, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·get_MkfifoatAddr(SB), NOSPLIT|NOFRAME, $0-8
|
|
||||||
MOVD $·Mkfifoat(SB), R8
|
|
||||||
MOVD R8, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·get_ChtagAddr(SB), NOSPLIT|NOFRAME, $0-8
|
|
||||||
MOVD $·Chtag(SB), R8
|
|
||||||
MOVD R8, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·get_ReadlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8
|
|
||||||
MOVD $·Readlinkat(SB), R8
|
|
||||||
MOVD R8, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
1
vendor/golang.org/x/sys/unix/syscall.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// 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 || zos
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
// Package unix contains an interface to the low-level operating system
|
// Package unix contains an interface to the low-level operating system
|
||||||
// primitives. OS details vary depending on the underlying system, and
|
// primitives. OS details vary depending on the underlying system, and
|
||||||
|
|||||||
21
vendor/golang.org/x/sys/unix/syscall_aix.go
generated
vendored
21
vendor/golang.org/x/sys/unix/syscall_aix.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix
|
//go:build aix
|
||||||
|
// +build aix
|
||||||
|
|
||||||
// Aix system calls.
|
// Aix system calls.
|
||||||
// This file is compiled as ordinary Go code,
|
// This file is compiled as ordinary Go code,
|
||||||
@@ -106,8 +107,7 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
|||||||
if n > 0 {
|
if n > 0 {
|
||||||
sl += _Socklen(n) + 1
|
sl += _Socklen(n) + 1
|
||||||
}
|
}
|
||||||
if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) {
|
if sa.raw.Path[0] == '@' {
|
||||||
// Check sl > 3 so we don't change unnamed socket behavior.
|
|
||||||
sa.raw.Path[0] = 0
|
sa.raw.Path[0] = 0
|
||||||
// Don't count trailing NUL for abstract address.
|
// Don't count trailing NUL for abstract address.
|
||||||
sl--
|
sl--
|
||||||
@@ -487,6 +487,8 @@ func Fsync(fd int) error {
|
|||||||
//sys Unlinkat(dirfd int, path string, flags int) (err error)
|
//sys Unlinkat(dirfd int, path string, flags int) (err error)
|
||||||
//sys Ustat(dev int, ubuf *Ustat_t) (err error)
|
//sys Ustat(dev int, ubuf *Ustat_t) (err error)
|
||||||
//sys write(fd int, p []byte) (n int, err error)
|
//sys write(fd int, p []byte) (n int, err error)
|
||||||
|
//sys readlen(fd int, p *byte, np int) (n int, err error) = read
|
||||||
|
//sys writelen(fd int, p *byte, np int) (n int, err error) = write
|
||||||
|
|
||||||
//sys Dup2(oldfd int, newfd int) (err error)
|
//sys Dup2(oldfd int, newfd int) (err error)
|
||||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = posix_fadvise64
|
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = posix_fadvise64
|
||||||
@@ -533,6 +535,21 @@ func Fsync(fd int) error {
|
|||||||
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = nsendmsg
|
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = nsendmsg
|
||||||
|
|
||||||
//sys munmap(addr uintptr, length uintptr) (err error)
|
//sys munmap(addr uintptr, length uintptr) (err error)
|
||||||
|
|
||||||
|
var mapper = &mmapper{
|
||||||
|
active: make(map[*byte][]byte),
|
||||||
|
mmap: mmap,
|
||||||
|
munmap: munmap,
|
||||||
|
}
|
||||||
|
|
||||||
|
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
|
||||||
|
return mapper.Mmap(fd, offset, length, prot, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Munmap(b []byte) (err error) {
|
||||||
|
return mapper.Munmap(b)
|
||||||
|
}
|
||||||
|
|
||||||
//sys Madvise(b []byte, advice int) (err error)
|
//sys Madvise(b []byte, advice int) (err error)
|
||||||
//sys Mprotect(b []byte, prot int) (err error)
|
//sys Mprotect(b []byte, prot int) (err error)
|
||||||
//sys Mlock(b []byte) (err error)
|
//sys Mlock(b []byte) (err error)
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/syscall_aix_ppc.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall_aix_ppc.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix && ppc
|
//go:build aix && ppc
|
||||||
|
// +build aix,ppc
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix && ppc64
|
//go:build aix && ppc64
|
||||||
|
// +build aix,ppc64
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
17
vendor/golang.org/x/sys/unix/syscall_bsd.go
generated
vendored
17
vendor/golang.org/x/sys/unix/syscall_bsd.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build darwin || dragonfly || freebsd || netbsd || openbsd
|
//go:build darwin || dragonfly || freebsd || netbsd || openbsd
|
||||||
|
// +build darwin dragonfly freebsd netbsd openbsd
|
||||||
|
|
||||||
// BSD system call wrappers shared by *BSD based systems
|
// BSD system call wrappers shared by *BSD based systems
|
||||||
// including OS X (Darwin) and FreeBSD. Like the other
|
// including OS X (Darwin) and FreeBSD. Like the other
|
||||||
@@ -316,7 +317,7 @@ func GetsockoptString(fd, level, opt int) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return ByteSliceToString(buf[:vallen]), nil
|
return string(buf[:vallen-1]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
|
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
|
||||||
@@ -600,6 +601,20 @@ func Poll(fds []PollFd, timeout int) (n int, err error) {
|
|||||||
// Gethostuuid(uuid *byte, timeout *Timespec) (err error)
|
// Gethostuuid(uuid *byte, timeout *Timespec) (err error)
|
||||||
// Ptrace(req int, pid int, addr uintptr, data int) (ret uintptr, err error)
|
// Ptrace(req int, pid int, addr uintptr, data int) (ret uintptr, err error)
|
||||||
|
|
||||||
|
var mapper = &mmapper{
|
||||||
|
active: make(map[*byte][]byte),
|
||||||
|
mmap: mmap,
|
||||||
|
munmap: munmap,
|
||||||
|
}
|
||||||
|
|
||||||
|
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
|
||||||
|
return mapper.Mmap(fd, offset, length, prot, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Munmap(b []byte) (err error) {
|
||||||
|
return mapper.Munmap(b)
|
||||||
|
}
|
||||||
|
|
||||||
//sys Madvise(b []byte, behav int) (err error)
|
//sys Madvise(b []byte, behav int) (err error)
|
||||||
//sys Mlock(b []byte) (err error)
|
//sys Mlock(b []byte) (err error)
|
||||||
//sys Mlockall(flags int) (err error)
|
//sys Mlockall(flags int) (err error)
|
||||||
|
|||||||
204
vendor/golang.org/x/sys/unix/syscall_darwin.go
generated
vendored
204
vendor/golang.org/x/sys/unix/syscall_darwin.go
generated
vendored
@@ -510,7 +510,6 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
|
||||||
// Find size.
|
// Find size.
|
||||||
n := uintptr(0)
|
n := uintptr(0)
|
||||||
if err := sysctl(mib, nil, &n, nil, 0); err != nil {
|
if err := sysctl(mib, nil, &n, nil, 0); err != nil {
|
||||||
@@ -526,10 +525,6 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
|
|||||||
// Read into buffer of that size.
|
// Read into buffer of that size.
|
||||||
buf := make([]KinfoProc, n/SizeofKinfoProc)
|
buf := make([]KinfoProc, n/SizeofKinfoProc)
|
||||||
if err := sysctl(mib, (*byte)(unsafe.Pointer(&buf[0])), &n, nil, 0); err != nil {
|
if err := sysctl(mib, (*byte)(unsafe.Pointer(&buf[0])), &n, nil, 0); err != nil {
|
||||||
if err == ENOMEM {
|
|
||||||
// Process table grew. Try again.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if n%SizeofKinfoProc != 0 {
|
if n%SizeofKinfoProc != 0 {
|
||||||
@@ -539,19 +534,6 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
|
|||||||
// The actual call may return less than the original reported required
|
// The actual call may return less than the original reported required
|
||||||
// size so ensure we deal with that.
|
// size so ensure we deal with that.
|
||||||
return buf[:n/SizeofKinfoProc], nil
|
return buf[:n/SizeofKinfoProc], nil
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//sys pthread_chdir_np(path string) (err error)
|
|
||||||
|
|
||||||
func PthreadChdir(path string) (err error) {
|
|
||||||
return pthread_chdir_np(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
//sys pthread_fchdir_np(fd int) (err error)
|
|
||||||
|
|
||||||
func PthreadFchdir(fd int) (err error) {
|
|
||||||
return pthread_fchdir_np(fd)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//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)
|
||||||
@@ -656,3 +638,189 @@ func PthreadFchdir(fd int) (err error) {
|
|||||||
//sys write(fd int, p []byte) (n int, err error)
|
//sys write(fd int, p []byte) (n int, err error)
|
||||||
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
|
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
|
||||||
//sys munmap(addr uintptr, length uintptr) (err error)
|
//sys munmap(addr uintptr, length uintptr) (err error)
|
||||||
|
//sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
|
||||||
|
//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unimplemented
|
||||||
|
*/
|
||||||
|
// Profil
|
||||||
|
// Sigaction
|
||||||
|
// Sigprocmask
|
||||||
|
// Getlogin
|
||||||
|
// Sigpending
|
||||||
|
// Sigaltstack
|
||||||
|
// Ioctl
|
||||||
|
// Reboot
|
||||||
|
// Execve
|
||||||
|
// Vfork
|
||||||
|
// Sbrk
|
||||||
|
// Sstk
|
||||||
|
// Ovadvise
|
||||||
|
// Mincore
|
||||||
|
// Setitimer
|
||||||
|
// Swapon
|
||||||
|
// Select
|
||||||
|
// Sigsuspend
|
||||||
|
// Readv
|
||||||
|
// Writev
|
||||||
|
// Nfssvc
|
||||||
|
// Getfh
|
||||||
|
// Quotactl
|
||||||
|
// Csops
|
||||||
|
// Waitid
|
||||||
|
// Add_profil
|
||||||
|
// Kdebug_trace
|
||||||
|
// Sigreturn
|
||||||
|
// Atsocket
|
||||||
|
// Kqueue_from_portset_np
|
||||||
|
// Kqueue_portset
|
||||||
|
// Getattrlist
|
||||||
|
// Getdirentriesattr
|
||||||
|
// Searchfs
|
||||||
|
// Delete
|
||||||
|
// Copyfile
|
||||||
|
// Watchevent
|
||||||
|
// Waitevent
|
||||||
|
// Modwatch
|
||||||
|
// Fsctl
|
||||||
|
// Initgroups
|
||||||
|
// Posix_spawn
|
||||||
|
// Nfsclnt
|
||||||
|
// Fhopen
|
||||||
|
// Minherit
|
||||||
|
// Semsys
|
||||||
|
// Msgsys
|
||||||
|
// Shmsys
|
||||||
|
// Semctl
|
||||||
|
// Semget
|
||||||
|
// Semop
|
||||||
|
// Msgctl
|
||||||
|
// Msgget
|
||||||
|
// Msgsnd
|
||||||
|
// Msgrcv
|
||||||
|
// Shm_open
|
||||||
|
// Shm_unlink
|
||||||
|
// Sem_open
|
||||||
|
// Sem_close
|
||||||
|
// Sem_unlink
|
||||||
|
// Sem_wait
|
||||||
|
// Sem_trywait
|
||||||
|
// Sem_post
|
||||||
|
// Sem_getvalue
|
||||||
|
// Sem_init
|
||||||
|
// Sem_destroy
|
||||||
|
// Open_extended
|
||||||
|
// Umask_extended
|
||||||
|
// Stat_extended
|
||||||
|
// Lstat_extended
|
||||||
|
// Fstat_extended
|
||||||
|
// Chmod_extended
|
||||||
|
// Fchmod_extended
|
||||||
|
// Access_extended
|
||||||
|
// Settid
|
||||||
|
// Gettid
|
||||||
|
// Setsgroups
|
||||||
|
// Getsgroups
|
||||||
|
// Setwgroups
|
||||||
|
// Getwgroups
|
||||||
|
// Mkfifo_extended
|
||||||
|
// Mkdir_extended
|
||||||
|
// Identitysvc
|
||||||
|
// Shared_region_check_np
|
||||||
|
// Shared_region_map_np
|
||||||
|
// __pthread_mutex_destroy
|
||||||
|
// __pthread_mutex_init
|
||||||
|
// __pthread_mutex_lock
|
||||||
|
// __pthread_mutex_trylock
|
||||||
|
// __pthread_mutex_unlock
|
||||||
|
// __pthread_cond_init
|
||||||
|
// __pthread_cond_destroy
|
||||||
|
// __pthread_cond_broadcast
|
||||||
|
// __pthread_cond_signal
|
||||||
|
// Setsid_with_pid
|
||||||
|
// __pthread_cond_timedwait
|
||||||
|
// Aio_fsync
|
||||||
|
// Aio_return
|
||||||
|
// Aio_suspend
|
||||||
|
// Aio_cancel
|
||||||
|
// Aio_error
|
||||||
|
// Aio_read
|
||||||
|
// Aio_write
|
||||||
|
// Lio_listio
|
||||||
|
// __pthread_cond_wait
|
||||||
|
// Iopolicysys
|
||||||
|
// __pthread_kill
|
||||||
|
// __pthread_sigmask
|
||||||
|
// __sigwait
|
||||||
|
// __disable_threadsignal
|
||||||
|
// __pthread_markcancel
|
||||||
|
// __pthread_canceled
|
||||||
|
// __semwait_signal
|
||||||
|
// Proc_info
|
||||||
|
// sendfile
|
||||||
|
// Stat64_extended
|
||||||
|
// Lstat64_extended
|
||||||
|
// Fstat64_extended
|
||||||
|
// __pthread_chdir
|
||||||
|
// __pthread_fchdir
|
||||||
|
// Audit
|
||||||
|
// Auditon
|
||||||
|
// Getauid
|
||||||
|
// Setauid
|
||||||
|
// Getaudit
|
||||||
|
// Setaudit
|
||||||
|
// Getaudit_addr
|
||||||
|
// Setaudit_addr
|
||||||
|
// Auditctl
|
||||||
|
// Bsdthread_create
|
||||||
|
// Bsdthread_terminate
|
||||||
|
// Stack_snapshot
|
||||||
|
// Bsdthread_register
|
||||||
|
// Workq_open
|
||||||
|
// Workq_ops
|
||||||
|
// __mac_execve
|
||||||
|
// __mac_syscall
|
||||||
|
// __mac_get_file
|
||||||
|
// __mac_set_file
|
||||||
|
// __mac_get_link
|
||||||
|
// __mac_set_link
|
||||||
|
// __mac_get_proc
|
||||||
|
// __mac_set_proc
|
||||||
|
// __mac_get_fd
|
||||||
|
// __mac_set_fd
|
||||||
|
// __mac_get_pid
|
||||||
|
// __mac_get_lcid
|
||||||
|
// __mac_get_lctx
|
||||||
|
// __mac_set_lctx
|
||||||
|
// Setlcid
|
||||||
|
// Read_nocancel
|
||||||
|
// Write_nocancel
|
||||||
|
// Open_nocancel
|
||||||
|
// Close_nocancel
|
||||||
|
// Wait4_nocancel
|
||||||
|
// Recvmsg_nocancel
|
||||||
|
// Sendmsg_nocancel
|
||||||
|
// Recvfrom_nocancel
|
||||||
|
// Accept_nocancel
|
||||||
|
// Fcntl_nocancel
|
||||||
|
// Select_nocancel
|
||||||
|
// Fsync_nocancel
|
||||||
|
// Connect_nocancel
|
||||||
|
// Sigsuspend_nocancel
|
||||||
|
// Readv_nocancel
|
||||||
|
// Writev_nocancel
|
||||||
|
// Sendto_nocancel
|
||||||
|
// Pread_nocancel
|
||||||
|
// Pwrite_nocancel
|
||||||
|
// Waitid_nocancel
|
||||||
|
// Poll_nocancel
|
||||||
|
// Msgsnd_nocancel
|
||||||
|
// Msgrcv_nocancel
|
||||||
|
// Sem_wait_nocancel
|
||||||
|
// Aio_suspend_nocancel
|
||||||
|
// __sigwait_nocancel
|
||||||
|
// __semwait_signal_nocancel
|
||||||
|
// __mac_mount
|
||||||
|
// __mac_get_mount
|
||||||
|
// __mac_getfsstat
|
||||||
|
|||||||
2
vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build amd64 && darwin
|
//go:build amd64 && darwin
|
||||||
|
// +build amd64,darwin
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
@@ -46,5 +47,6 @@ func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
|
|||||||
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64
|
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64
|
||||||
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
|
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
|
||||||
//sys ptrace1(request int, pid int, addr uintptr, data uintptr) (err error) = SYS_ptrace
|
//sys ptrace1(request int, pid int, addr uintptr, data uintptr) (err error) = SYS_ptrace
|
||||||
|
//sys ptrace1Ptr(request int, pid int, addr unsafe.Pointer, data uintptr) (err error) = SYS_ptrace
|
||||||
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
|
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
|
||||||
//sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64
|
//sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64
|
||||||
|
|||||||
2
vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build arm64 && darwin
|
//go:build arm64 && darwin
|
||||||
|
// +build arm64,darwin
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
@@ -46,5 +47,6 @@ func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
|
|||||||
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT
|
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT
|
||||||
//sys Lstat(path string, stat *Stat_t) (err error)
|
//sys Lstat(path string, stat *Stat_t) (err error)
|
||||||
//sys ptrace1(request int, pid int, addr uintptr, data uintptr) (err error) = SYS_ptrace
|
//sys ptrace1(request int, pid int, addr uintptr, data uintptr) (err error) = SYS_ptrace
|
||||||
|
//sys ptrace1Ptr(request int, pid int, addr unsafe.Pointer, data uintptr) (err error) = SYS_ptrace
|
||||||
//sys Stat(path string, stat *Stat_t) (err error)
|
//sys Stat(path string, stat *Stat_t) (err error)
|
||||||
//sys Statfs(path string, stat *Statfs_t) (err error)
|
//sys Statfs(path string, stat *Statfs_t) (err error)
|
||||||
|
|||||||
3
vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go
generated
vendored
3
vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go
generated
vendored
@@ -2,7 +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 darwin
|
//go:build darwin && go1.12
|
||||||
|
// +build darwin,go1.12
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
198
vendor/golang.org/x/sys/unix/syscall_dragonfly.go
generated
vendored
198
vendor/golang.org/x/sys/unix/syscall_dragonfly.go
generated
vendored
@@ -343,5 +343,203 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
|||||||
//sys write(fd int, p []byte) (n int, err error)
|
//sys write(fd int, p []byte) (n int, err error)
|
||||||
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
|
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
|
||||||
//sys munmap(addr uintptr, length uintptr) (err error)
|
//sys munmap(addr uintptr, length uintptr) (err error)
|
||||||
|
//sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
|
||||||
|
//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
|
||||||
//sys accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error)
|
//sys accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error)
|
||||||
//sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error)
|
//sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unimplemented
|
||||||
|
* TODO(jsing): Update this list for DragonFly.
|
||||||
|
*/
|
||||||
|
// Profil
|
||||||
|
// Sigaction
|
||||||
|
// Sigprocmask
|
||||||
|
// Getlogin
|
||||||
|
// Sigpending
|
||||||
|
// Sigaltstack
|
||||||
|
// Reboot
|
||||||
|
// Execve
|
||||||
|
// Vfork
|
||||||
|
// Sbrk
|
||||||
|
// Sstk
|
||||||
|
// Ovadvise
|
||||||
|
// Mincore
|
||||||
|
// Setitimer
|
||||||
|
// Swapon
|
||||||
|
// Select
|
||||||
|
// Sigsuspend
|
||||||
|
// Readv
|
||||||
|
// Writev
|
||||||
|
// Nfssvc
|
||||||
|
// Getfh
|
||||||
|
// Quotactl
|
||||||
|
// Mount
|
||||||
|
// Csops
|
||||||
|
// Waitid
|
||||||
|
// Add_profil
|
||||||
|
// Kdebug_trace
|
||||||
|
// Sigreturn
|
||||||
|
// Atsocket
|
||||||
|
// Kqueue_from_portset_np
|
||||||
|
// Kqueue_portset
|
||||||
|
// Getattrlist
|
||||||
|
// Setattrlist
|
||||||
|
// Getdirentriesattr
|
||||||
|
// Searchfs
|
||||||
|
// Delete
|
||||||
|
// Copyfile
|
||||||
|
// Watchevent
|
||||||
|
// Waitevent
|
||||||
|
// Modwatch
|
||||||
|
// Getxattr
|
||||||
|
// Fgetxattr
|
||||||
|
// Setxattr
|
||||||
|
// Fsetxattr
|
||||||
|
// Removexattr
|
||||||
|
// Fremovexattr
|
||||||
|
// Listxattr
|
||||||
|
// Flistxattr
|
||||||
|
// Fsctl
|
||||||
|
// Initgroups
|
||||||
|
// Posix_spawn
|
||||||
|
// Nfsclnt
|
||||||
|
// Fhopen
|
||||||
|
// Minherit
|
||||||
|
// Semsys
|
||||||
|
// Msgsys
|
||||||
|
// Shmsys
|
||||||
|
// Semctl
|
||||||
|
// Semget
|
||||||
|
// Semop
|
||||||
|
// Msgctl
|
||||||
|
// Msgget
|
||||||
|
// Msgsnd
|
||||||
|
// Msgrcv
|
||||||
|
// Shmat
|
||||||
|
// Shmctl
|
||||||
|
// Shmdt
|
||||||
|
// Shmget
|
||||||
|
// Shm_open
|
||||||
|
// Shm_unlink
|
||||||
|
// Sem_open
|
||||||
|
// Sem_close
|
||||||
|
// Sem_unlink
|
||||||
|
// Sem_wait
|
||||||
|
// Sem_trywait
|
||||||
|
// Sem_post
|
||||||
|
// Sem_getvalue
|
||||||
|
// Sem_init
|
||||||
|
// Sem_destroy
|
||||||
|
// Open_extended
|
||||||
|
// Umask_extended
|
||||||
|
// Stat_extended
|
||||||
|
// Lstat_extended
|
||||||
|
// Fstat_extended
|
||||||
|
// Chmod_extended
|
||||||
|
// Fchmod_extended
|
||||||
|
// Access_extended
|
||||||
|
// Settid
|
||||||
|
// Gettid
|
||||||
|
// Setsgroups
|
||||||
|
// Getsgroups
|
||||||
|
// Setwgroups
|
||||||
|
// Getwgroups
|
||||||
|
// Mkfifo_extended
|
||||||
|
// Mkdir_extended
|
||||||
|
// Identitysvc
|
||||||
|
// Shared_region_check_np
|
||||||
|
// Shared_region_map_np
|
||||||
|
// __pthread_mutex_destroy
|
||||||
|
// __pthread_mutex_init
|
||||||
|
// __pthread_mutex_lock
|
||||||
|
// __pthread_mutex_trylock
|
||||||
|
// __pthread_mutex_unlock
|
||||||
|
// __pthread_cond_init
|
||||||
|
// __pthread_cond_destroy
|
||||||
|
// __pthread_cond_broadcast
|
||||||
|
// __pthread_cond_signal
|
||||||
|
// Setsid_with_pid
|
||||||
|
// __pthread_cond_timedwait
|
||||||
|
// Aio_fsync
|
||||||
|
// Aio_return
|
||||||
|
// Aio_suspend
|
||||||
|
// Aio_cancel
|
||||||
|
// Aio_error
|
||||||
|
// Aio_read
|
||||||
|
// Aio_write
|
||||||
|
// Lio_listio
|
||||||
|
// __pthread_cond_wait
|
||||||
|
// Iopolicysys
|
||||||
|
// __pthread_kill
|
||||||
|
// __pthread_sigmask
|
||||||
|
// __sigwait
|
||||||
|
// __disable_threadsignal
|
||||||
|
// __pthread_markcancel
|
||||||
|
// __pthread_canceled
|
||||||
|
// __semwait_signal
|
||||||
|
// Proc_info
|
||||||
|
// Stat64_extended
|
||||||
|
// Lstat64_extended
|
||||||
|
// Fstat64_extended
|
||||||
|
// __pthread_chdir
|
||||||
|
// __pthread_fchdir
|
||||||
|
// Audit
|
||||||
|
// Auditon
|
||||||
|
// Getauid
|
||||||
|
// Setauid
|
||||||
|
// Getaudit
|
||||||
|
// Setaudit
|
||||||
|
// Getaudit_addr
|
||||||
|
// Setaudit_addr
|
||||||
|
// Auditctl
|
||||||
|
// Bsdthread_create
|
||||||
|
// Bsdthread_terminate
|
||||||
|
// Stack_snapshot
|
||||||
|
// Bsdthread_register
|
||||||
|
// Workq_open
|
||||||
|
// Workq_ops
|
||||||
|
// __mac_execve
|
||||||
|
// __mac_syscall
|
||||||
|
// __mac_get_file
|
||||||
|
// __mac_set_file
|
||||||
|
// __mac_get_link
|
||||||
|
// __mac_set_link
|
||||||
|
// __mac_get_proc
|
||||||
|
// __mac_set_proc
|
||||||
|
// __mac_get_fd
|
||||||
|
// __mac_set_fd
|
||||||
|
// __mac_get_pid
|
||||||
|
// __mac_get_lcid
|
||||||
|
// __mac_get_lctx
|
||||||
|
// __mac_set_lctx
|
||||||
|
// Setlcid
|
||||||
|
// Read_nocancel
|
||||||
|
// Write_nocancel
|
||||||
|
// Open_nocancel
|
||||||
|
// Close_nocancel
|
||||||
|
// Wait4_nocancel
|
||||||
|
// Recvmsg_nocancel
|
||||||
|
// Sendmsg_nocancel
|
||||||
|
// Recvfrom_nocancel
|
||||||
|
// Accept_nocancel
|
||||||
|
// Fcntl_nocancel
|
||||||
|
// Select_nocancel
|
||||||
|
// Fsync_nocancel
|
||||||
|
// Connect_nocancel
|
||||||
|
// Sigsuspend_nocancel
|
||||||
|
// Readv_nocancel
|
||||||
|
// Writev_nocancel
|
||||||
|
// Sendto_nocancel
|
||||||
|
// Pread_nocancel
|
||||||
|
// Pwrite_nocancel
|
||||||
|
// Waitid_nocancel
|
||||||
|
// Msgsnd_nocancel
|
||||||
|
// Msgrcv_nocancel
|
||||||
|
// Sem_wait_nocancel
|
||||||
|
// Aio_suspend_nocancel
|
||||||
|
// __sigwait_nocancel
|
||||||
|
// __semwait_signal_nocancel
|
||||||
|
// __mac_mount
|
||||||
|
// __mac_get_mount
|
||||||
|
// __mac_getfsstat
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build amd64 && dragonfly
|
//go:build amd64 && dragonfly
|
||||||
|
// +build amd64,dragonfly
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
204
vendor/golang.org/x/sys/unix/syscall_freebsd.go
generated
vendored
204
vendor/golang.org/x/sys/unix/syscall_freebsd.go
generated
vendored
@@ -13,7 +13,6 @@
|
|||||||
package unix
|
package unix
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@@ -170,26 +169,25 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
|||||||
func Uname(uname *Utsname) error {
|
func Uname(uname *Utsname) error {
|
||||||
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
|
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
|
||||||
n := unsafe.Sizeof(uname.Sysname)
|
n := unsafe.Sizeof(uname.Sysname)
|
||||||
// Suppress ENOMEM errors to be compatible with the C library __xuname() implementation.
|
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil {
|
||||||
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
|
mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
|
||||||
n = unsafe.Sizeof(uname.Nodename)
|
n = unsafe.Sizeof(uname.Nodename)
|
||||||
if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
|
if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
|
mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
|
||||||
n = unsafe.Sizeof(uname.Release)
|
n = unsafe.Sizeof(uname.Release)
|
||||||
if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
|
if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mib = []_C_int{CTL_KERN, KERN_VERSION}
|
mib = []_C_int{CTL_KERN, KERN_VERSION}
|
||||||
n = unsafe.Sizeof(uname.Version)
|
n = unsafe.Sizeof(uname.Version)
|
||||||
if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
|
if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +205,7 @@ func Uname(uname *Utsname) error {
|
|||||||
|
|
||||||
mib = []_C_int{CTL_HW, HW_MACHINE}
|
mib = []_C_int{CTL_HW, HW_MACHINE}
|
||||||
n = unsafe.Sizeof(uname.Machine)
|
n = unsafe.Sizeof(uname.Machine)
|
||||||
if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
|
if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,5 +449,197 @@ func Dup3(oldfd, newfd, flags int) error {
|
|||||||
//sys write(fd int, p []byte) (n int, err error)
|
//sys write(fd int, p []byte) (n int, err error)
|
||||||
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
|
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
|
||||||
//sys munmap(addr uintptr, length uintptr) (err error)
|
//sys munmap(addr uintptr, length uintptr) (err error)
|
||||||
|
//sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
|
||||||
|
//sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
|
||||||
//sys accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error)
|
//sys accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error)
|
||||||
//sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error)
|
//sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unimplemented
|
||||||
|
*/
|
||||||
|
// Profil
|
||||||
|
// Sigaction
|
||||||
|
// Sigprocmask
|
||||||
|
// Getlogin
|
||||||
|
// Sigpending
|
||||||
|
// Sigaltstack
|
||||||
|
// Ioctl
|
||||||
|
// Reboot
|
||||||
|
// Execve
|
||||||
|
// Vfork
|
||||||
|
// Sbrk
|
||||||
|
// Sstk
|
||||||
|
// Ovadvise
|
||||||
|
// Mincore
|
||||||
|
// Setitimer
|
||||||
|
// Swapon
|
||||||
|
// Select
|
||||||
|
// Sigsuspend
|
||||||
|
// Readv
|
||||||
|
// Writev
|
||||||
|
// Nfssvc
|
||||||
|
// Getfh
|
||||||
|
// Quotactl
|
||||||
|
// Mount
|
||||||
|
// Csops
|
||||||
|
// Waitid
|
||||||
|
// Add_profil
|
||||||
|
// Kdebug_trace
|
||||||
|
// Sigreturn
|
||||||
|
// Atsocket
|
||||||
|
// Kqueue_from_portset_np
|
||||||
|
// Kqueue_portset
|
||||||
|
// Getattrlist
|
||||||
|
// Setattrlist
|
||||||
|
// Getdents
|
||||||
|
// Getdirentriesattr
|
||||||
|
// Searchfs
|
||||||
|
// Delete
|
||||||
|
// Copyfile
|
||||||
|
// Watchevent
|
||||||
|
// Waitevent
|
||||||
|
// Modwatch
|
||||||
|
// Fsctl
|
||||||
|
// Initgroups
|
||||||
|
// Posix_spawn
|
||||||
|
// Nfsclnt
|
||||||
|
// Fhopen
|
||||||
|
// Minherit
|
||||||
|
// Semsys
|
||||||
|
// Msgsys
|
||||||
|
// Shmsys
|
||||||
|
// Semctl
|
||||||
|
// Semget
|
||||||
|
// Semop
|
||||||
|
// Msgctl
|
||||||
|
// Msgget
|
||||||
|
// Msgsnd
|
||||||
|
// Msgrcv
|
||||||
|
// Shmat
|
||||||
|
// Shmctl
|
||||||
|
// Shmdt
|
||||||
|
// Shmget
|
||||||
|
// Shm_open
|
||||||
|
// Shm_unlink
|
||||||
|
// Sem_open
|
||||||
|
// Sem_close
|
||||||
|
// Sem_unlink
|
||||||
|
// Sem_wait
|
||||||
|
// Sem_trywait
|
||||||
|
// Sem_post
|
||||||
|
// Sem_getvalue
|
||||||
|
// Sem_init
|
||||||
|
// Sem_destroy
|
||||||
|
// Open_extended
|
||||||
|
// Umask_extended
|
||||||
|
// Stat_extended
|
||||||
|
// Lstat_extended
|
||||||
|
// Fstat_extended
|
||||||
|
// Chmod_extended
|
||||||
|
// Fchmod_extended
|
||||||
|
// Access_extended
|
||||||
|
// Settid
|
||||||
|
// Gettid
|
||||||
|
// Setsgroups
|
||||||
|
// Getsgroups
|
||||||
|
// Setwgroups
|
||||||
|
// Getwgroups
|
||||||
|
// Mkfifo_extended
|
||||||
|
// Mkdir_extended
|
||||||
|
// Identitysvc
|
||||||
|
// Shared_region_check_np
|
||||||
|
// Shared_region_map_np
|
||||||
|
// __pthread_mutex_destroy
|
||||||
|
// __pthread_mutex_init
|
||||||
|
// __pthread_mutex_lock
|
||||||
|
// __pthread_mutex_trylock
|
||||||
|
// __pthread_mutex_unlock
|
||||||
|
// __pthread_cond_init
|
||||||
|
// __pthread_cond_destroy
|
||||||
|
// __pthread_cond_broadcast
|
||||||
|
// __pthread_cond_signal
|
||||||
|
// Setsid_with_pid
|
||||||
|
// __pthread_cond_timedwait
|
||||||
|
// Aio_fsync
|
||||||
|
// Aio_return
|
||||||
|
// Aio_suspend
|
||||||
|
// Aio_cancel
|
||||||
|
// Aio_error
|
||||||
|
// Aio_read
|
||||||
|
// Aio_write
|
||||||
|
// Lio_listio
|
||||||
|
// __pthread_cond_wait
|
||||||
|
// Iopolicysys
|
||||||
|
// __pthread_kill
|
||||||
|
// __pthread_sigmask
|
||||||
|
// __sigwait
|
||||||
|
// __disable_threadsignal
|
||||||
|
// __pthread_markcancel
|
||||||
|
// __pthread_canceled
|
||||||
|
// __semwait_signal
|
||||||
|
// Proc_info
|
||||||
|
// Stat64_extended
|
||||||
|
// Lstat64_extended
|
||||||
|
// Fstat64_extended
|
||||||
|
// __pthread_chdir
|
||||||
|
// __pthread_fchdir
|
||||||
|
// Audit
|
||||||
|
// Auditon
|
||||||
|
// Getauid
|
||||||
|
// Setauid
|
||||||
|
// Getaudit
|
||||||
|
// Setaudit
|
||||||
|
// Getaudit_addr
|
||||||
|
// Setaudit_addr
|
||||||
|
// Auditctl
|
||||||
|
// Bsdthread_create
|
||||||
|
// Bsdthread_terminate
|
||||||
|
// Stack_snapshot
|
||||||
|
// Bsdthread_register
|
||||||
|
// Workq_open
|
||||||
|
// Workq_ops
|
||||||
|
// __mac_execve
|
||||||
|
// __mac_syscall
|
||||||
|
// __mac_get_file
|
||||||
|
// __mac_set_file
|
||||||
|
// __mac_get_link
|
||||||
|
// __mac_set_link
|
||||||
|
// __mac_get_proc
|
||||||
|
// __mac_set_proc
|
||||||
|
// __mac_get_fd
|
||||||
|
// __mac_set_fd
|
||||||
|
// __mac_get_pid
|
||||||
|
// __mac_get_lcid
|
||||||
|
// __mac_get_lctx
|
||||||
|
// __mac_set_lctx
|
||||||
|
// Setlcid
|
||||||
|
// Read_nocancel
|
||||||
|
// Write_nocancel
|
||||||
|
// Open_nocancel
|
||||||
|
// Close_nocancel
|
||||||
|
// Wait4_nocancel
|
||||||
|
// Recvmsg_nocancel
|
||||||
|
// Sendmsg_nocancel
|
||||||
|
// Recvfrom_nocancel
|
||||||
|
// Accept_nocancel
|
||||||
|
// Fcntl_nocancel
|
||||||
|
// Select_nocancel
|
||||||
|
// Fsync_nocancel
|
||||||
|
// Connect_nocancel
|
||||||
|
// Sigsuspend_nocancel
|
||||||
|
// Readv_nocancel
|
||||||
|
// Writev_nocancel
|
||||||
|
// Sendto_nocancel
|
||||||
|
// Pread_nocancel
|
||||||
|
// Pwrite_nocancel
|
||||||
|
// Waitid_nocancel
|
||||||
|
// Poll_nocancel
|
||||||
|
// Msgsnd_nocancel
|
||||||
|
// Msgrcv_nocancel
|
||||||
|
// Sem_wait_nocancel
|
||||||
|
// Aio_suspend_nocancel
|
||||||
|
// __sigwait_nocancel
|
||||||
|
// __semwait_signal_nocancel
|
||||||
|
// __mac_mount
|
||||||
|
// __mac_get_mount
|
||||||
|
// __mac_getfsstat
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/syscall_freebsd_386.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall_freebsd_386.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build 386 && freebsd
|
//go:build 386 && freebsd
|
||||||
|
// +build 386,freebsd
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build amd64 && freebsd
|
//go:build amd64 && freebsd
|
||||||
|
// +build amd64,freebsd
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build arm && freebsd
|
//go:build arm && freebsd
|
||||||
|
// +build arm,freebsd
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build arm64 && freebsd
|
//go:build arm64 && freebsd
|
||||||
|
// +build arm64,freebsd
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall_freebsd_riscv64.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build riscv64 && freebsd
|
//go:build riscv64 && freebsd
|
||||||
|
// +build riscv64,freebsd
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/syscall_hurd.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall_hurd.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build hurd
|
//go:build hurd
|
||||||
|
// +build hurd
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
1
vendor/golang.org/x/sys/unix/syscall_hurd_386.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall_hurd_386.go
generated
vendored
@@ -3,6 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build 386 && hurd
|
//go:build 386 && hurd
|
||||||
|
// +build 386,hurd
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user