Update vendoring (#801)
* Update vendor github.com/godbus/dbus@v4.1.0 * Update vendor github.com/golang/protobuf/proto * Update vendor github.com/mdlayher/netlink/... * Update vendor github.com/prometheus/client_golang/prometheus/... * Update vendor github.com/prometheus/client_model/go * Update vendor github.com/prometheus/common/... * Update vendor github.com/prometheus/procfs/... * Update vendor github.com/sirupsen/logrus@v1.0.4 * Update vendor golang.org/x/... * Update vendor gopkg.in/alecthomas/kingpin.v2 * Remove obsolete vendor github.com/mdlayher/netlink/genetlinkpull/805/head
parent
4ed49e73fb
commit
f9e91156d0
|
@ -27,6 +27,10 @@ var (
|
||||||
|
|
||||||
// A Conn is a connection to netlink. A Conn can be used to send and
|
// A Conn is a connection to netlink. A Conn can be used to send and
|
||||||
// receives messages to and from netlink.
|
// receives messages to and from netlink.
|
||||||
|
//
|
||||||
|
// A Conn is safe for concurrent use, but to avoid contention in
|
||||||
|
// high-throughput applications, the caller should almost certainly create a
|
||||||
|
// pool of Conns and distribute them among workers.
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
// sock is the operating system-specific implementation of
|
// sock is the operating system-specific implementation of
|
||||||
// a netlink sockets connection.
|
// a netlink sockets connection.
|
||||||
|
@ -330,4 +334,14 @@ type Config struct {
|
||||||
// Groups is a bitmask which specifies multicast groups. If set to 0,
|
// Groups is a bitmask which specifies multicast groups. If set to 0,
|
||||||
// no multicast group subscriptions will be made.
|
// no multicast group subscriptions will be made.
|
||||||
Groups uint32
|
Groups uint32
|
||||||
|
|
||||||
|
// Experimental: do not lock the internal system call handling goroutine
|
||||||
|
// to its OS thread. This may result in a speed-up of system call handling,
|
||||||
|
// but may cause unexpected behavior when sending and receiving a large number
|
||||||
|
// of messages.
|
||||||
|
//
|
||||||
|
// This should almost certainly be set to false, but if you come up with a
|
||||||
|
// valid reason for using this, please file an issue at
|
||||||
|
// https://github.com/mdlayher/netlink to discuss your thoughts.
|
||||||
|
NoLockThread bool
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ package netlink
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
@ -39,16 +41,23 @@ type socket interface {
|
||||||
// dial is the entry point for Dial. dial opens a netlink socket using
|
// dial is the entry point for Dial. dial opens a netlink socket using
|
||||||
// system calls, and returns its PID.
|
// system calls, and returns its PID.
|
||||||
func dial(family int, config *Config) (*conn, uint32, error) {
|
func dial(family int, config *Config) (*conn, uint32, error) {
|
||||||
fd, err := unix.Socket(
|
// Prepare sysSocket's internal loop and create the socket.
|
||||||
unix.AF_NETLINK,
|
//
|
||||||
unix.SOCK_RAW,
|
// The conditional is inverted because a zero value of false is desired
|
||||||
family,
|
// if no config, but it's easier to interpret within this code when the
|
||||||
)
|
// value is inverted.
|
||||||
if err != nil {
|
if config == nil {
|
||||||
|
config = &Config{}
|
||||||
|
}
|
||||||
|
|
||||||
|
lockThread := !config.NoLockThread
|
||||||
|
sock := newSysSocket(lockThread)
|
||||||
|
|
||||||
|
if err := sock.Socket(family); err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return bind(&sysSocket{fd: fd}, config)
|
return bind(sock, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind binds a connection to netlink using the input socket, which may be
|
// bind binds a connection to netlink using the input socket, which may be
|
||||||
|
@ -213,18 +222,144 @@ var _ socket = &sysSocket{}
|
||||||
// A sysSocket is a socket which uses system calls for socket operations.
|
// A sysSocket is a socket which uses system calls for socket operations.
|
||||||
type sysSocket struct {
|
type sysSocket struct {
|
||||||
fd int
|
fd int
|
||||||
|
|
||||||
|
wg *sync.WaitGroup
|
||||||
|
funcC chan<- func()
|
||||||
|
}
|
||||||
|
|
||||||
|
// newSysSocket creates a sysSocket that optionally locks its internal goroutine
|
||||||
|
// to a single thread.
|
||||||
|
func newSysSocket(lockThread bool) *sysSocket {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
// This system call loop strategy was inspired by:
|
||||||
|
// https://github.com/golang/go/wiki/LockOSThread. Thanks to squeed on
|
||||||
|
// Gophers Slack for providing this useful link.
|
||||||
|
|
||||||
|
funcC := make(chan func())
|
||||||
|
go func() {
|
||||||
|
// It is important to lock this goroutine to its OS thread for the duration
|
||||||
|
// of the netlink socket being used, or else the kernel may end up routing
|
||||||
|
// messages to the wrong places.
|
||||||
|
// See: http://lists.infradead.org/pipermail/libnl/2017-February/002293.html.
|
||||||
|
//
|
||||||
|
// But since this is very experimental, we'll leave it as a configurable at
|
||||||
|
// this point.
|
||||||
|
if lockThread {
|
||||||
|
// Never unlock the OS thread, so that the thread will terminate when
|
||||||
|
// the goroutine exits starting in Go 1.10:
|
||||||
|
// https://go-review.googlesource.com/c/go/+/46038.
|
||||||
|
runtime.LockOSThread()
|
||||||
|
}
|
||||||
|
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
for f := range funcC {
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return &sysSocket{
|
||||||
|
wg: &wg,
|
||||||
|
funcC: funcC,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// do runs f in a worker goroutine which can be locked to one thread.
|
||||||
|
func (s *sysSocket) do(f func()) {
|
||||||
|
done := make(chan bool, 1)
|
||||||
|
s.funcC <- func() {
|
||||||
|
f()
|
||||||
|
done <- true
|
||||||
|
}
|
||||||
|
<-done
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sysSocket) Socket(family int) error {
|
||||||
|
var (
|
||||||
|
fd int
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
s.do(func() {
|
||||||
|
fd, err = unix.Socket(
|
||||||
|
unix.AF_NETLINK,
|
||||||
|
unix.SOCK_RAW,
|
||||||
|
family,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.fd = fd
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sysSocket) Bind(sa unix.Sockaddr) error {
|
||||||
|
var err error
|
||||||
|
s.do(func() {
|
||||||
|
err = unix.Bind(s.fd, sa)
|
||||||
|
})
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sysSocket) Close() error {
|
||||||
|
var err error
|
||||||
|
s.do(func() {
|
||||||
|
err = unix.Close(s.fd)
|
||||||
|
})
|
||||||
|
|
||||||
|
close(s.funcC)
|
||||||
|
s.wg.Wait()
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysSocket) Bind(sa unix.Sockaddr) error { return unix.Bind(s.fd, sa) }
|
|
||||||
func (s *sysSocket) Close() error { return unix.Close(s.fd) }
|
|
||||||
func (s *sysSocket) FD() int { return s.fd }
|
func (s *sysSocket) FD() int { return s.fd }
|
||||||
func (s *sysSocket) Getsockname() (unix.Sockaddr, error) { return unix.Getsockname(s.fd) }
|
|
||||||
|
func (s *sysSocket) Getsockname() (unix.Sockaddr, error) {
|
||||||
|
var (
|
||||||
|
sa unix.Sockaddr
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
s.do(func() {
|
||||||
|
sa, err = unix.Getsockname(s.fd)
|
||||||
|
})
|
||||||
|
|
||||||
|
return sa, err
|
||||||
|
}
|
||||||
func (s *sysSocket) Recvmsg(p, oob []byte, flags int) (int, int, int, unix.Sockaddr, error) {
|
func (s *sysSocket) Recvmsg(p, oob []byte, flags int) (int, int, int, unix.Sockaddr, error) {
|
||||||
return unix.Recvmsg(s.fd, p, oob, flags)
|
var (
|
||||||
|
n, oobn, recvflags int
|
||||||
|
from unix.Sockaddr
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
s.do(func() {
|
||||||
|
n, oobn, recvflags, from, err = unix.Recvmsg(s.fd, p, oob, flags)
|
||||||
|
})
|
||||||
|
|
||||||
|
return n, oobn, recvflags, from, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysSocket) Sendmsg(p, oob []byte, to unix.Sockaddr, flags int) error {
|
func (s *sysSocket) Sendmsg(p, oob []byte, to unix.Sockaddr, flags int) error {
|
||||||
return unix.Sendmsg(s.fd, p, oob, to, flags)
|
var err error
|
||||||
|
s.do(func() {
|
||||||
|
err = unix.Sendmsg(s.fd, p, oob, to, flags)
|
||||||
|
})
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysSocket) SetSockopt(level, name int, v unsafe.Pointer, l uint32) error {
|
func (s *sysSocket) SetSockopt(level, name int, v unsafe.Pointer, l uint32) error {
|
||||||
return setsockopt(s.fd, level, name, v, l)
|
var err error
|
||||||
|
s.do(func() {
|
||||||
|
err = setsockopt(s.fd, level, name, v, l)
|
||||||
|
})
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,20 @@ const (
|
||||||
// HeaderFlagsDump requests that netlink return a complete list of
|
// HeaderFlagsDump requests that netlink return a complete list of
|
||||||
// all entries.
|
// all entries.
|
||||||
HeaderFlagsDump HeaderFlags = HeaderFlagsRoot | HeaderFlagsMatch
|
HeaderFlagsDump HeaderFlags = HeaderFlagsRoot | HeaderFlagsMatch
|
||||||
|
|
||||||
|
// Flags used to create objects.
|
||||||
|
|
||||||
|
// HeaderFlagsReplace indicates request replaces an existing matching object.
|
||||||
|
HeaderFlagsReplace HeaderFlags = 0x100
|
||||||
|
|
||||||
|
// HeaderFlagsExcl indicates request does not replace the object if it already exists.
|
||||||
|
HeaderFlagsExcl HeaderFlags = 0x200
|
||||||
|
|
||||||
|
// HeaderFlagsCreate indicates request creates an object if it doesn't already exist.
|
||||||
|
HeaderFlagsCreate HeaderFlags = 0x400
|
||||||
|
|
||||||
|
// HeaderFlagsAppend indicates request adds to the end of the object list.
|
||||||
|
HeaderFlagsAppend HeaderFlags = 0x800
|
||||||
)
|
)
|
||||||
|
|
||||||
// String returns the string representation of a HeaderFlags.
|
// String returns the string representation of a HeaderFlags.
|
||||||
|
@ -73,14 +87,12 @@ func (f HeaderFlags) String() string {
|
||||||
"echo",
|
"echo",
|
||||||
"dumpinterrupted",
|
"dumpinterrupted",
|
||||||
"dumpfiltered",
|
"dumpfiltered",
|
||||||
"1<<6",
|
|
||||||
"1<<7",
|
|
||||||
"root",
|
|
||||||
"match",
|
|
||||||
"atomic",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var s string
|
var s string
|
||||||
|
|
||||||
|
left := uint(f)
|
||||||
|
|
||||||
for i, name := range names {
|
for i, name := range names {
|
||||||
if f&(1<<uint(i)) != 0 {
|
if f&(1<<uint(i)) != 0 {
|
||||||
if s != "" {
|
if s != "" {
|
||||||
|
@ -88,13 +100,22 @@ func (f HeaderFlags) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
s += name
|
s += name
|
||||||
|
|
||||||
|
left ^= (1 << uint(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s == "" {
|
if s == "" && left == 0 {
|
||||||
s = "0"
|
s = "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if left > 0 {
|
||||||
|
if s != "" {
|
||||||
|
s += "|"
|
||||||
|
}
|
||||||
|
s += fmt.Sprintf("%#x", left)
|
||||||
|
}
|
||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,8 +233,17 @@ func (m *Message) UnmarshalBinary(b []byte) error {
|
||||||
func checkMessage(m Message) error {
|
func checkMessage(m Message) error {
|
||||||
const success = 0
|
const success = 0
|
||||||
|
|
||||||
// HeaderTypeError may indicate an error code, or success
|
// Both "done" and "error" can contain error codes.
|
||||||
if m.Header.Type != HeaderTypeError {
|
isDone := m.Header.Type == HeaderTypeDone
|
||||||
|
isError := m.Header.Type == HeaderTypeError
|
||||||
|
|
||||||
|
switch {
|
||||||
|
// "done" with no data means success.
|
||||||
|
case isDone && len(m.Data) == 0:
|
||||||
|
return nil
|
||||||
|
case isError, isDone:
|
||||||
|
break
|
||||||
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,10 @@ package prometheus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"math"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
dto "github.com/prometheus/client_model/go"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Counter is a Metric that represents a single numerical value that only ever
|
// Counter is a Metric that represents a single numerical value that only ever
|
||||||
|
@ -42,6 +46,14 @@ type Counter interface {
|
||||||
type CounterOpts Opts
|
type CounterOpts Opts
|
||||||
|
|
||||||
// NewCounter creates a new Counter based on the provided CounterOpts.
|
// NewCounter creates a new Counter based on the provided CounterOpts.
|
||||||
|
//
|
||||||
|
// The returned implementation tracks the counter value in two separate
|
||||||
|
// variables, a float64 and a uint64. The latter is used to track calls of the
|
||||||
|
// Inc method and calls of the Add method with a value that can be represented
|
||||||
|
// as a uint64. This allows atomic increments of the counter with optimal
|
||||||
|
// performance. (It is common to have an Inc call in very hot execution paths.)
|
||||||
|
// Both internal tracking values are added up in the Write method. This has to
|
||||||
|
// be taken into account when it comes to precision and overflow behavior.
|
||||||
func NewCounter(opts CounterOpts) Counter {
|
func NewCounter(opts CounterOpts) Counter {
|
||||||
desc := NewDesc(
|
desc := NewDesc(
|
||||||
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
||||||
|
@ -49,20 +61,58 @@ func NewCounter(opts CounterOpts) Counter {
|
||||||
nil,
|
nil,
|
||||||
opts.ConstLabels,
|
opts.ConstLabels,
|
||||||
)
|
)
|
||||||
result := &counter{value: value{desc: desc, valType: CounterValue, labelPairs: desc.constLabelPairs}}
|
result := &counter{desc: desc, labelPairs: desc.constLabelPairs}
|
||||||
result.init(result) // Init self-collection.
|
result.init(result) // Init self-collection.
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
type counter struct {
|
type counter struct {
|
||||||
value
|
// valBits contains the bits of the represented float64 value, while
|
||||||
|
// valInt stores values that are exact integers. Both have to go first
|
||||||
|
// in the struct to guarantee alignment for atomic operations.
|
||||||
|
// http://golang.org/pkg/sync/atomic/#pkg-note-BUG
|
||||||
|
valBits uint64
|
||||||
|
valInt uint64
|
||||||
|
|
||||||
|
selfCollector
|
||||||
|
desc *Desc
|
||||||
|
|
||||||
|
labelPairs []*dto.LabelPair
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *counter) Desc() *Desc {
|
||||||
|
return c.desc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *counter) Add(v float64) {
|
func (c *counter) Add(v float64) {
|
||||||
if v < 0 {
|
if v < 0 {
|
||||||
panic(errors.New("counter cannot decrease in value"))
|
panic(errors.New("counter cannot decrease in value"))
|
||||||
}
|
}
|
||||||
c.value.Add(v)
|
ival := uint64(v)
|
||||||
|
if float64(ival) == v {
|
||||||
|
atomic.AddUint64(&c.valInt, ival)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
oldBits := atomic.LoadUint64(&c.valBits)
|
||||||
|
newBits := math.Float64bits(math.Float64frombits(oldBits) + v)
|
||||||
|
if atomic.CompareAndSwapUint64(&c.valBits, oldBits, newBits) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *counter) Inc() {
|
||||||
|
atomic.AddUint64(&c.valInt, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *counter) Write(out *dto.Metric) error {
|
||||||
|
fval := math.Float64frombits(atomic.LoadUint64(&c.valBits))
|
||||||
|
ival := atomic.LoadUint64(&c.valInt)
|
||||||
|
val := fval + float64(ival)
|
||||||
|
|
||||||
|
return populateMetric(CounterValue, val, c.labelPairs, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CounterVec is a Collector that bundles a set of Counters that all share the
|
// CounterVec is a Collector that bundles a set of Counters that all share the
|
||||||
|
@ -85,11 +135,10 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
|
||||||
)
|
)
|
||||||
return &CounterVec{
|
return &CounterVec{
|
||||||
metricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
metricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
||||||
result := &counter{value: value{
|
if len(lvs) != len(desc.variableLabels) {
|
||||||
desc: desc,
|
panic(errInconsistentCardinality)
|
||||||
valType: CounterValue,
|
}
|
||||||
labelPairs: makeLabelPairs(desc, lvs),
|
result := &counter{desc: desc, labelPairs: makeLabelPairs(desc, lvs)}
|
||||||
}}
|
|
||||||
result.init(result) // Init self-collection.
|
result.init(result) // Init self-collection.
|
||||||
return result
|
return result
|
||||||
}),
|
}),
|
||||||
|
@ -111,7 +160,7 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
|
||||||
// Counter with the same label values is created later.
|
// Counter with the same label values is created later.
|
||||||
//
|
//
|
||||||
// An error is returned if the number of label values is not the same as the
|
// An error is returned if the number of label values is not the same as the
|
||||||
// number of VariableLabels in Desc.
|
// number of VariableLabels in Desc (minus any curried labels).
|
||||||
//
|
//
|
||||||
// Note that for more than one label value, this method is prone to mistakes
|
// Note that for more than one label value, this method is prone to mistakes
|
||||||
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
|
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
|
||||||
|
@ -119,8 +168,8 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
|
||||||
// latter has a much more readable (albeit more verbose) syntax, but it comes
|
// latter has a much more readable (albeit more verbose) syntax, but it comes
|
||||||
// with a performance overhead (for creating and processing the Labels map).
|
// with a performance overhead (for creating and processing the Labels map).
|
||||||
// See also the GaugeVec example.
|
// See also the GaugeVec example.
|
||||||
func (m *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
|
func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
|
||||||
metric, err := m.metricVec.getMetricWithLabelValues(lvs...)
|
metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
|
||||||
if metric != nil {
|
if metric != nil {
|
||||||
return metric.(Counter), err
|
return metric.(Counter), err
|
||||||
}
|
}
|
||||||
|
@ -134,13 +183,13 @@ func (m *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
|
||||||
// the same as for GetMetricWithLabelValues.
|
// the same as for GetMetricWithLabelValues.
|
||||||
//
|
//
|
||||||
// An error is returned if the number and names of the Labels are inconsistent
|
// An error is returned if the number and names of the Labels are inconsistent
|
||||||
// with those of the VariableLabels in Desc.
|
// with those of the VariableLabels in Desc (minus any curried labels).
|
||||||
//
|
//
|
||||||
// This method is used for the same purpose as
|
// This method is used for the same purpose as
|
||||||
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
||||||
// methods.
|
// methods.
|
||||||
func (m *CounterVec) GetMetricWith(labels Labels) (Counter, error) {
|
func (v *CounterVec) GetMetricWith(labels Labels) (Counter, error) {
|
||||||
metric, err := m.metricVec.getMetricWith(labels)
|
metric, err := v.metricVec.getMetricWith(labels)
|
||||||
if metric != nil {
|
if metric != nil {
|
||||||
return metric.(Counter), err
|
return metric.(Counter), err
|
||||||
}
|
}
|
||||||
|
@ -148,18 +197,57 @@ func (m *CounterVec) GetMetricWith(labels Labels) (Counter, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithLabelValues works as GetMetricWithLabelValues, but panics where
|
// WithLabelValues works as GetMetricWithLabelValues, but panics where
|
||||||
// GetMetricWithLabelValues would have returned an error. By not returning an
|
// GetMetricWithLabelValues would have returned an error. Not returning an
|
||||||
// error, WithLabelValues allows shortcuts like
|
// error allows shortcuts like
|
||||||
// myVec.WithLabelValues("404", "GET").Add(42)
|
// myVec.WithLabelValues("404", "GET").Add(42)
|
||||||
func (m *CounterVec) WithLabelValues(lvs ...string) Counter {
|
func (v *CounterVec) WithLabelValues(lvs ...string) Counter {
|
||||||
return m.metricVec.withLabelValues(lvs...).(Counter)
|
c, err := v.GetMetricWithLabelValues(lvs...)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// With works as GetMetricWith, but panics where GetMetricWithLabels would have
|
// With works as GetMetricWith, but panics where GetMetricWithLabels would have
|
||||||
// returned an error. By not returning an error, With allows shortcuts like
|
// returned an error. Not returning an error allows shortcuts like
|
||||||
// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42)
|
// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42)
|
||||||
func (m *CounterVec) With(labels Labels) Counter {
|
func (v *CounterVec) With(labels Labels) Counter {
|
||||||
return m.metricVec.with(labels).(Counter)
|
c, err := v.GetMetricWith(labels)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurryWith returns a vector curried with the provided labels, i.e. the
|
||||||
|
// returned vector has those labels pre-set for all labeled operations performed
|
||||||
|
// on it. The cardinality of the curried vector is reduced accordingly. The
|
||||||
|
// order of the remaining labels stays the same (just with the curried labels
|
||||||
|
// taken out of the sequence – which is relevant for the
|
||||||
|
// (GetMetric)WithLabelValues methods). It is possible to curry a curried
|
||||||
|
// vector, but only with labels not yet used for currying before.
|
||||||
|
//
|
||||||
|
// The metrics contained in the CounterVec are shared between the curried and
|
||||||
|
// uncurried vectors. They are just accessed differently. Curried and uncurried
|
||||||
|
// vectors behave identically in terms of collection. Only one must be
|
||||||
|
// registered with a given registry (usually the uncurried version). The Reset
|
||||||
|
// method deletes all metrics, even if called on a curried vector.
|
||||||
|
func (v *CounterVec) CurryWith(labels Labels) (*CounterVec, error) {
|
||||||
|
vec, err := v.curryWith(labels)
|
||||||
|
if vec != nil {
|
||||||
|
return &CounterVec{vec}, err
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustCurryWith works as CurryWith but panics where CurryWith would have
|
||||||
|
// returned an error.
|
||||||
|
func (v *CounterVec) MustCurryWith(labels Labels) *CounterVec {
|
||||||
|
vec, err := v.CurryWith(labels)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return vec
|
||||||
}
|
}
|
||||||
|
|
||||||
// CounterFunc is a Counter whose value is determined at collect time by calling a
|
// CounterFunc is a Counter whose value is determined at collect time by calling a
|
||||||
|
|
|
@ -73,8 +73,7 @@ type Desc struct {
|
||||||
// and therefore not part of the Desc. (They are managed within the Metric.)
|
// and therefore not part of the Desc. (They are managed within the Metric.)
|
||||||
//
|
//
|
||||||
// For constLabels, the label values are constant. Therefore, they are fully
|
// For constLabels, the label values are constant. Therefore, they are fully
|
||||||
// specified in the Desc. See the Opts documentation for the implications of
|
// specified in the Desc. See the Collector example for a usage pattern.
|
||||||
// constant labels.
|
|
||||||
func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *Desc {
|
func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *Desc {
|
||||||
d := &Desc{
|
d := &Desc{
|
||||||
fqName: fqName,
|
fqName: fqName,
|
||||||
|
|
|
@ -145,7 +145,7 @@
|
||||||
// registry.
|
// registry.
|
||||||
//
|
//
|
||||||
// So far, everything we did operated on the so-called default registry, as it
|
// So far, everything we did operated on the so-called default registry, as it
|
||||||
// can be found in the global DefaultRegistry variable. With NewRegistry, you
|
// can be found in the global DefaultRegisterer variable. With NewRegistry, you
|
||||||
// can create a custom registry, or you can even implement the Registerer or
|
// can create a custom registry, or you can even implement the Registerer or
|
||||||
// Gatherer interfaces yourself. The methods Register and Unregister work in the
|
// Gatherer interfaces yourself. The methods Register and Unregister work in the
|
||||||
// same way on a custom registry as the global functions Register and Unregister
|
// same way on a custom registry as the global functions Register and Unregister
|
||||||
|
@ -153,11 +153,11 @@
|
||||||
//
|
//
|
||||||
// There are a number of uses for custom registries: You can use registries with
|
// There are a number of uses for custom registries: You can use registries with
|
||||||
// special properties, see NewPedanticRegistry. You can avoid global state, as
|
// special properties, see NewPedanticRegistry. You can avoid global state, as
|
||||||
// it is imposed by the DefaultRegistry. You can use multiple registries at the
|
// it is imposed by the DefaultRegisterer. You can use multiple registries at
|
||||||
// same time to expose different metrics in different ways. You can use separate
|
// the same time to expose different metrics in different ways. You can use
|
||||||
// registries for testing purposes.
|
// separate registries for testing purposes.
|
||||||
//
|
//
|
||||||
// Also note that the DefaultRegistry comes registered with a Collector for Go
|
// Also note that the DefaultRegisterer comes registered with a Collector for Go
|
||||||
// runtime metrics (via NewGoCollector) and a Collector for process metrics (via
|
// runtime metrics (via NewGoCollector) and a Collector for process metrics (via
|
||||||
// NewProcessCollector). With a custom registry, you are in control and decide
|
// NewProcessCollector). With a custom registry, you are in control and decide
|
||||||
// yourself about the Collectors to register.
|
// yourself about the Collectors to register.
|
||||||
|
|
|
@ -13,6 +13,14 @@
|
||||||
|
|
||||||
package prometheus
|
package prometheus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
)
|
||||||
|
|
||||||
// Gauge is a Metric that represents a single numerical value that can
|
// Gauge is a Metric that represents a single numerical value that can
|
||||||
// arbitrarily go up and down.
|
// arbitrarily go up and down.
|
||||||
//
|
//
|
||||||
|
@ -48,13 +56,74 @@ type Gauge interface {
|
||||||
type GaugeOpts Opts
|
type GaugeOpts Opts
|
||||||
|
|
||||||
// NewGauge creates a new Gauge based on the provided GaugeOpts.
|
// NewGauge creates a new Gauge based on the provided GaugeOpts.
|
||||||
|
//
|
||||||
|
// The returned implementation is optimized for a fast Set method. If you have a
|
||||||
|
// choice for managing the value of a Gauge via Set vs. Inc/Dec/Add/Sub, pick
|
||||||
|
// the former. For example, the Inc method of the returned Gauge is slower than
|
||||||
|
// the Inc method of a Counter returned by NewCounter. This matches the typical
|
||||||
|
// scenarios for Gauges and Counters, where the former tends to be Set-heavy and
|
||||||
|
// the latter Inc-heavy.
|
||||||
func NewGauge(opts GaugeOpts) Gauge {
|
func NewGauge(opts GaugeOpts) Gauge {
|
||||||
return newValue(NewDesc(
|
desc := NewDesc(
|
||||||
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
||||||
opts.Help,
|
opts.Help,
|
||||||
nil,
|
nil,
|
||||||
opts.ConstLabels,
|
opts.ConstLabels,
|
||||||
), GaugeValue, 0)
|
)
|
||||||
|
result := &gauge{desc: desc, labelPairs: desc.constLabelPairs}
|
||||||
|
result.init(result) // Init self-collection.
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
type gauge struct {
|
||||||
|
// valBits contains the bits of the represented float64 value. It has
|
||||||
|
// to go first in the struct to guarantee alignment for atomic
|
||||||
|
// operations. http://golang.org/pkg/sync/atomic/#pkg-note-BUG
|
||||||
|
valBits uint64
|
||||||
|
|
||||||
|
selfCollector
|
||||||
|
|
||||||
|
desc *Desc
|
||||||
|
labelPairs []*dto.LabelPair
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gauge) Desc() *Desc {
|
||||||
|
return g.desc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gauge) Set(val float64) {
|
||||||
|
atomic.StoreUint64(&g.valBits, math.Float64bits(val))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gauge) SetToCurrentTime() {
|
||||||
|
g.Set(float64(time.Now().UnixNano()) / 1e9)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gauge) Inc() {
|
||||||
|
g.Add(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gauge) Dec() {
|
||||||
|
g.Add(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gauge) Add(val float64) {
|
||||||
|
for {
|
||||||
|
oldBits := atomic.LoadUint64(&g.valBits)
|
||||||
|
newBits := math.Float64bits(math.Float64frombits(oldBits) + val)
|
||||||
|
if atomic.CompareAndSwapUint64(&g.valBits, oldBits, newBits) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gauge) Sub(val float64) {
|
||||||
|
g.Add(val * -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gauge) Write(out *dto.Metric) error {
|
||||||
|
val := math.Float64frombits(atomic.LoadUint64(&g.valBits))
|
||||||
|
return populateMetric(GaugeValue, val, g.labelPairs, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GaugeVec is a Collector that bundles a set of Gauges that all share the same
|
// GaugeVec is a Collector that bundles a set of Gauges that all share the same
|
||||||
|
@ -77,7 +146,12 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
|
||||||
)
|
)
|
||||||
return &GaugeVec{
|
return &GaugeVec{
|
||||||
metricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
metricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
||||||
return newValue(desc, GaugeValue, 0, lvs...)
|
if len(lvs) != len(desc.variableLabels) {
|
||||||
|
panic(errInconsistentCardinality)
|
||||||
|
}
|
||||||
|
result := &gauge{desc: desc, labelPairs: makeLabelPairs(desc, lvs)}
|
||||||
|
result.init(result) // Init self-collection.
|
||||||
|
return result
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,15 +172,15 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
|
||||||
// example.
|
// example.
|
||||||
//
|
//
|
||||||
// An error is returned if the number of label values is not the same as the
|
// An error is returned if the number of label values is not the same as the
|
||||||
// number of VariableLabels in Desc.
|
// number of VariableLabels in Desc (minus any curried labels).
|
||||||
//
|
//
|
||||||
// Note that for more than one label value, this method is prone to mistakes
|
// Note that for more than one label value, this method is prone to mistakes
|
||||||
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
|
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
|
||||||
// an alternative to avoid that type of mistake. For higher label numbers, the
|
// an alternative to avoid that type of mistake. For higher label numbers, the
|
||||||
// latter has a much more readable (albeit more verbose) syntax, but it comes
|
// latter has a much more readable (albeit more verbose) syntax, but it comes
|
||||||
// with a performance overhead (for creating and processing the Labels map).
|
// with a performance overhead (for creating and processing the Labels map).
|
||||||
func (m *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
|
func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
|
||||||
metric, err := m.metricVec.getMetricWithLabelValues(lvs...)
|
metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
|
||||||
if metric != nil {
|
if metric != nil {
|
||||||
return metric.(Gauge), err
|
return metric.(Gauge), err
|
||||||
}
|
}
|
||||||
|
@ -120,13 +194,13 @@ func (m *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
|
||||||
// the same as for GetMetricWithLabelValues.
|
// the same as for GetMetricWithLabelValues.
|
||||||
//
|
//
|
||||||
// An error is returned if the number and names of the Labels are inconsistent
|
// An error is returned if the number and names of the Labels are inconsistent
|
||||||
// with those of the VariableLabels in Desc.
|
// with those of the VariableLabels in Desc (minus any curried labels).
|
||||||
//
|
//
|
||||||
// This method is used for the same purpose as
|
// This method is used for the same purpose as
|
||||||
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
||||||
// methods.
|
// methods.
|
||||||
func (m *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
|
func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
|
||||||
metric, err := m.metricVec.getMetricWith(labels)
|
metric, err := v.metricVec.getMetricWith(labels)
|
||||||
if metric != nil {
|
if metric != nil {
|
||||||
return metric.(Gauge), err
|
return metric.(Gauge), err
|
||||||
}
|
}
|
||||||
|
@ -134,18 +208,57 @@ func (m *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithLabelValues works as GetMetricWithLabelValues, but panics where
|
// WithLabelValues works as GetMetricWithLabelValues, but panics where
|
||||||
// GetMetricWithLabelValues would have returned an error. By not returning an
|
// GetMetricWithLabelValues would have returned an error. Not returning an
|
||||||
// error, WithLabelValues allows shortcuts like
|
// error allows shortcuts like
|
||||||
// myVec.WithLabelValues("404", "GET").Add(42)
|
// myVec.WithLabelValues("404", "GET").Add(42)
|
||||||
func (m *GaugeVec) WithLabelValues(lvs ...string) Gauge {
|
func (v *GaugeVec) WithLabelValues(lvs ...string) Gauge {
|
||||||
return m.metricVec.withLabelValues(lvs...).(Gauge)
|
g, err := v.GetMetricWithLabelValues(lvs...)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
// With works as GetMetricWith, but panics where GetMetricWithLabels would have
|
// With works as GetMetricWith, but panics where GetMetricWithLabels would have
|
||||||
// returned an error. By not returning an error, With allows shortcuts like
|
// returned an error. Not returning an error allows shortcuts like
|
||||||
// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42)
|
// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42)
|
||||||
func (m *GaugeVec) With(labels Labels) Gauge {
|
func (v *GaugeVec) With(labels Labels) Gauge {
|
||||||
return m.metricVec.with(labels).(Gauge)
|
g, err := v.GetMetricWith(labels)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurryWith returns a vector curried with the provided labels, i.e. the
|
||||||
|
// returned vector has those labels pre-set for all labeled operations performed
|
||||||
|
// on it. The cardinality of the curried vector is reduced accordingly. The
|
||||||
|
// order of the remaining labels stays the same (just with the curried labels
|
||||||
|
// taken out of the sequence – which is relevant for the
|
||||||
|
// (GetMetric)WithLabelValues methods). It is possible to curry a curried
|
||||||
|
// vector, but only with labels not yet used for currying before.
|
||||||
|
//
|
||||||
|
// The metrics contained in the GaugeVec are shared between the curried and
|
||||||
|
// uncurried vectors. They are just accessed differently. Curried and uncurried
|
||||||
|
// vectors behave identically in terms of collection. Only one must be
|
||||||
|
// registered with a given registry (usually the uncurried version). The Reset
|
||||||
|
// method deletes all metrics, even if called on a curried vector.
|
||||||
|
func (v *GaugeVec) CurryWith(labels Labels) (*GaugeVec, error) {
|
||||||
|
vec, err := v.curryWith(labels)
|
||||||
|
if vec != nil {
|
||||||
|
return &GaugeVec{vec}, err
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustCurryWith works as CurryWith but panics where CurryWith would have
|
||||||
|
// returned an error.
|
||||||
|
func (v *GaugeVec) MustCurryWith(labels Labels) *GaugeVec {
|
||||||
|
vec, err := v.CurryWith(labels)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return vec
|
||||||
}
|
}
|
||||||
|
|
||||||
// GaugeFunc is a Gauge whose value is determined at collect time by calling a
|
// GaugeFunc is a Gauge whose value is determined at collect time by calling a
|
||||||
|
|
|
@ -126,23 +126,16 @@ type HistogramOpts struct {
|
||||||
// string.
|
// string.
|
||||||
Help string
|
Help string
|
||||||
|
|
||||||
// ConstLabels are used to attach fixed labels to this
|
// ConstLabels are used to attach fixed labels to this metric. Metrics
|
||||||
// Histogram. Histograms with the same fully-qualified name must have the
|
// with the same fully-qualified name must have the same label names in
|
||||||
// same label names in their ConstLabels.
|
// their ConstLabels.
|
||||||
//
|
//
|
||||||
// Note that in most cases, labels have a value that varies during the
|
// ConstLabels are only used rarely. In particular, do not use them to
|
||||||
// lifetime of a process. Those labels are usually managed with a
|
// attach the same labels to all your metrics. Those use cases are
|
||||||
// HistogramVec. ConstLabels serve only special purposes. One is for the
|
// better covered by target labels set by the scraping Prometheus
|
||||||
// special case where the value of a label does not change during the
|
// server, or by one specific metric (e.g. a build_info or a
|
||||||
// lifetime of a process, e.g. if the revision of the running binary is
|
// machine_role metric). See also
|
||||||
// put into a label. Another, more advanced purpose is if more than one
|
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
|
||||||
// Collector needs to collect Histograms with the same fully-qualified
|
|
||||||
// name. In that case, those Summaries must differ in the values of
|
|
||||||
// their ConstLabels. See the Collector examples.
|
|
||||||
//
|
|
||||||
// If the value of a label never changes (not even between binaries),
|
|
||||||
// that label most likely should not be a label at all (but part of the
|
|
||||||
// metric name).
|
|
||||||
ConstLabels Labels
|
ConstLabels Labels
|
||||||
|
|
||||||
// Buckets defines the buckets into which observations are counted. Each
|
// Buckets defines the buckets into which observations are counted. Each
|
||||||
|
@ -322,7 +315,7 @@ func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
|
||||||
// example.
|
// example.
|
||||||
//
|
//
|
||||||
// An error is returned if the number of label values is not the same as the
|
// An error is returned if the number of label values is not the same as the
|
||||||
// number of VariableLabels in Desc.
|
// number of VariableLabels in Desc (minus any curried labels).
|
||||||
//
|
//
|
||||||
// Note that for more than one label value, this method is prone to mistakes
|
// Note that for more than one label value, this method is prone to mistakes
|
||||||
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
|
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
|
||||||
|
@ -330,8 +323,8 @@ func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
|
||||||
// latter has a much more readable (albeit more verbose) syntax, but it comes
|
// latter has a much more readable (albeit more verbose) syntax, but it comes
|
||||||
// with a performance overhead (for creating and processing the Labels map).
|
// with a performance overhead (for creating and processing the Labels map).
|
||||||
// See also the GaugeVec example.
|
// See also the GaugeVec example.
|
||||||
func (m *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
|
func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
|
||||||
metric, err := m.metricVec.getMetricWithLabelValues(lvs...)
|
metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
|
||||||
if metric != nil {
|
if metric != nil {
|
||||||
return metric.(Observer), err
|
return metric.(Observer), err
|
||||||
}
|
}
|
||||||
|
@ -345,13 +338,13 @@ func (m *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error)
|
||||||
// are the same as for GetMetricWithLabelValues.
|
// are the same as for GetMetricWithLabelValues.
|
||||||
//
|
//
|
||||||
// An error is returned if the number and names of the Labels are inconsistent
|
// An error is returned if the number and names of the Labels are inconsistent
|
||||||
// with those of the VariableLabels in Desc.
|
// with those of the VariableLabels in Desc (minus any curried labels).
|
||||||
//
|
//
|
||||||
// This method is used for the same purpose as
|
// This method is used for the same purpose as
|
||||||
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
||||||
// methods.
|
// methods.
|
||||||
func (m *HistogramVec) GetMetricWith(labels Labels) (Observer, error) {
|
func (v *HistogramVec) GetMetricWith(labels Labels) (Observer, error) {
|
||||||
metric, err := m.metricVec.getMetricWith(labels)
|
metric, err := v.metricVec.getMetricWith(labels)
|
||||||
if metric != nil {
|
if metric != nil {
|
||||||
return metric.(Observer), err
|
return metric.(Observer), err
|
||||||
}
|
}
|
||||||
|
@ -359,18 +352,57 @@ func (m *HistogramVec) GetMetricWith(labels Labels) (Observer, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithLabelValues works as GetMetricWithLabelValues, but panics where
|
// WithLabelValues works as GetMetricWithLabelValues, but panics where
|
||||||
// GetMetricWithLabelValues would have returned an error. By not returning an
|
// GetMetricWithLabelValues would have returned an error. Not returning an
|
||||||
// error, WithLabelValues allows shortcuts like
|
// error allows shortcuts like
|
||||||
// myVec.WithLabelValues("404", "GET").Observe(42.21)
|
// myVec.WithLabelValues("404", "GET").Observe(42.21)
|
||||||
func (m *HistogramVec) WithLabelValues(lvs ...string) Observer {
|
func (v *HistogramVec) WithLabelValues(lvs ...string) Observer {
|
||||||
return m.metricVec.withLabelValues(lvs...).(Observer)
|
h, err := v.GetMetricWithLabelValues(lvs...)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
// With works as GetMetricWith, but panics where GetMetricWithLabels would have
|
// With works as GetMetricWith but panics where GetMetricWithLabels would have
|
||||||
// returned an error. By not returning an error, With allows shortcuts like
|
// returned an error. Not returning an error allows shortcuts like
|
||||||
// myVec.With(Labels{"code": "404", "method": "GET"}).Observe(42.21)
|
// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21)
|
||||||
func (m *HistogramVec) With(labels Labels) Observer {
|
func (v *HistogramVec) With(labels Labels) Observer {
|
||||||
return m.metricVec.with(labels).(Observer)
|
h, err := v.GetMetricWith(labels)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurryWith returns a vector curried with the provided labels, i.e. the
|
||||||
|
// returned vector has those labels pre-set for all labeled operations performed
|
||||||
|
// on it. The cardinality of the curried vector is reduced accordingly. The
|
||||||
|
// order of the remaining labels stays the same (just with the curried labels
|
||||||
|
// taken out of the sequence – which is relevant for the
|
||||||
|
// (GetMetric)WithLabelValues methods). It is possible to curry a curried
|
||||||
|
// vector, but only with labels not yet used for currying before.
|
||||||
|
//
|
||||||
|
// The metrics contained in the HistogramVec are shared between the curried and
|
||||||
|
// uncurried vectors. They are just accessed differently. Curried and uncurried
|
||||||
|
// vectors behave identically in terms of collection. Only one must be
|
||||||
|
// registered with a given registry (usually the uncurried version). The Reset
|
||||||
|
// method deletes all metrics, even if called on a curried vector.
|
||||||
|
func (v *HistogramVec) CurryWith(labels Labels) (ObserverVec, error) {
|
||||||
|
vec, err := v.curryWith(labels)
|
||||||
|
if vec != nil {
|
||||||
|
return &HistogramVec{vec}, err
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustCurryWith works as CurryWith but panics where CurryWith would have
|
||||||
|
// returned an error.
|
||||||
|
func (v *HistogramVec) MustCurryWith(labels Labels) ObserverVec {
|
||||||
|
vec, err := v.CurryWith(labels)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return vec
|
||||||
}
|
}
|
||||||
|
|
||||||
type constHistogram struct {
|
type constHistogram struct {
|
||||||
|
|
|
@ -79,20 +79,12 @@ type Opts struct {
|
||||||
// with the same fully-qualified name must have the same label names in
|
// with the same fully-qualified name must have the same label names in
|
||||||
// their ConstLabels.
|
// their ConstLabels.
|
||||||
//
|
//
|
||||||
// Note that in most cases, labels have a value that varies during the
|
// ConstLabels are only used rarely. In particular, do not use them to
|
||||||
// lifetime of a process. Those labels are usually managed with a metric
|
// attach the same labels to all your metrics. Those use cases are
|
||||||
// vector collector (like CounterVec, GaugeVec, UntypedVec). ConstLabels
|
// better covered by target labels set by the scraping Prometheus
|
||||||
// serve only special purposes. One is for the special case where the
|
// server, or by one specific metric (e.g. a build_info or a
|
||||||
// value of a label does not change during the lifetime of a process,
|
// machine_role metric). See also
|
||||||
// e.g. if the revision of the running binary is put into a
|
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
|
||||||
// label. Another, more advanced purpose is if more than one Collector
|
|
||||||
// needs to collect Metrics with the same fully-qualified name. In that
|
|
||||||
// case, those Metrics must differ in the values of their
|
|
||||||
// ConstLabels. See the Collector examples.
|
|
||||||
//
|
|
||||||
// If the value of a label never changes (not even between binaries),
|
|
||||||
// that label most likely should not be a label at all (but part of the
|
|
||||||
// metric name).
|
|
||||||
ConstLabels Labels
|
ConstLabels Labels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,8 @@ type ObserverVec interface {
|
||||||
GetMetricWithLabelValues(lvs ...string) (Observer, error)
|
GetMetricWithLabelValues(lvs ...string) (Observer, error)
|
||||||
With(Labels) Observer
|
With(Labels) Observer
|
||||||
WithLabelValues(...string) Observer
|
WithLabelValues(...string) Observer
|
||||||
|
CurryWith(Labels) (ObserverVec, error)
|
||||||
|
MustCurryWith(Labels) ObserverVec
|
||||||
|
|
||||||
Collector
|
Collector
|
||||||
}
|
}
|
||||||
|
|
29
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go
generated
vendored
29
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go
generated
vendored
|
@ -45,12 +45,11 @@ func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripp
|
||||||
|
|
||||||
// InstrumentRoundTripperCounter is a middleware that wraps the provided
|
// InstrumentRoundTripperCounter is a middleware that wraps the provided
|
||||||
// http.RoundTripper to observe the request result with the provided CounterVec.
|
// http.RoundTripper to observe the request result with the provided CounterVec.
|
||||||
// The CounterVec must have zero, one, or two labels. The only allowed label
|
// The CounterVec must have zero, one, or two non-const non-curried labels. For
|
||||||
// names are "code" and "method". The function panics if any other instance
|
// those, the only allowed label names are "code" and "method". The function
|
||||||
// labels are provided. Partitioning of the CounterVec happens by HTTP status
|
// panics otherwise. Partitioning of the CounterVec happens by HTTP status code
|
||||||
// code and/or HTTP method if the respective instance label names are present
|
// and/or HTTP method if the respective instance label names are present in the
|
||||||
// in the CounterVec. For unpartitioned counting, use a CounterVec with
|
// CounterVec. For unpartitioned counting, use a CounterVec with zero labels.
|
||||||
// zero labels.
|
|
||||||
//
|
//
|
||||||
// If the wrapped RoundTripper panics or returns a non-nil error, the Counter
|
// If the wrapped RoundTripper panics or returns a non-nil error, the Counter
|
||||||
// is not incremented.
|
// is not incremented.
|
||||||
|
@ -69,15 +68,15 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstrumentRoundTripperDuration is a middleware that wraps the provided
|
// InstrumentRoundTripperDuration is a middleware that wraps the provided
|
||||||
// http.RoundTripper to observe the request duration with the provided ObserverVec.
|
// http.RoundTripper to observe the request duration with the provided
|
||||||
// The ObserverVec must have zero, one, or two labels. The only allowed label
|
// ObserverVec. The ObserverVec must have zero, one, or two non-const
|
||||||
// names are "code" and "method". The function panics if any other instance
|
// non-curried labels. For those, the only allowed label names are "code" and
|
||||||
// labels are provided. The Observe method of the Observer in the ObserverVec
|
// "method". The function panics otherwise. The Observe method of the Observer
|
||||||
// is called with the request duration in seconds. Partitioning happens by HTTP
|
// in the ObserverVec is called with the request duration in
|
||||||
// status code and/or HTTP method if the respective instance label names are
|
// seconds. Partitioning happens by HTTP status code and/or HTTP method if the
|
||||||
// present in the ObserverVec. For unpartitioned observations, use an
|
// respective instance label names are present in the ObserverVec. For
|
||||||
// ObserverVec with zero labels. Note that partitioning of Histograms is
|
// unpartitioned observations, use an ObserverVec with zero labels. Note that
|
||||||
// expensive and should be used judiciously.
|
// partitioning of Histograms is expensive and should be used judiciously.
|
||||||
//
|
//
|
||||||
// If the wrapped RoundTripper panics or returns a non-nil error, no values are
|
// If the wrapped RoundTripper panics or returns a non-nil error, no values are
|
||||||
// reported.
|
// reported.
|
||||||
|
|
129
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
generated
vendored
129
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
generated
vendored
|
@ -14,6 +14,7 @@
|
||||||
package promhttp
|
package promhttp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -42,10 +43,10 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl
|
||||||
|
|
||||||
// InstrumentHandlerDuration is a middleware that wraps the provided
|
// InstrumentHandlerDuration is a middleware that wraps the provided
|
||||||
// http.Handler to observe the request duration with the provided ObserverVec.
|
// http.Handler to observe the request duration with the provided ObserverVec.
|
||||||
// The ObserverVec must have zero, one, or two labels. The only allowed label
|
// The ObserverVec must have zero, one, or two non-const non-curried labels. For
|
||||||
// names are "code" and "method". The function panics if any other instance
|
// those, the only allowed label names are "code" and "method". The function
|
||||||
// labels are provided. The Observe method of the Observer in the ObserverVec
|
// panics otherwise. The Observe method of the Observer in the ObserverVec is
|
||||||
// is called with the request duration in seconds. Partitioning happens by HTTP
|
// called with the request duration in seconds. Partitioning happens by HTTP
|
||||||
// status code and/or HTTP method if the respective instance label names are
|
// status code and/or HTTP method if the respective instance label names are
|
||||||
// present in the ObserverVec. For unpartitioned observations, use an
|
// present in the ObserverVec. For unpartitioned observations, use an
|
||||||
// ObserverVec with zero labels. Note that partitioning of Histograms is
|
// ObserverVec with zero labels. Note that partitioning of Histograms is
|
||||||
|
@ -77,14 +78,13 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstrumentHandlerCounter is a middleware that wraps the provided
|
// InstrumentHandlerCounter is a middleware that wraps the provided http.Handler
|
||||||
// http.Handler to observe the request result with the provided CounterVec.
|
// to observe the request result with the provided CounterVec. The CounterVec
|
||||||
// The CounterVec must have zero, one, or two labels. The only allowed label
|
// must have zero, one, or two non-const non-curried labels. For those, the only
|
||||||
// names are "code" and "method". The function panics if any other instance
|
// allowed label names are "code" and "method". The function panics
|
||||||
// labels are provided. Partitioning of the CounterVec happens by HTTP status
|
// otherwise. Partitioning of the CounterVec happens by HTTP status code and/or
|
||||||
// code and/or HTTP method if the respective instance label names are present
|
// HTTP method if the respective instance label names are present in the
|
||||||
// in the CounterVec. For unpartitioned counting, use a CounterVec with
|
// CounterVec. For unpartitioned counting, use a CounterVec with zero labels.
|
||||||
// zero labels.
|
|
||||||
//
|
//
|
||||||
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
|
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
|
||||||
//
|
//
|
||||||
|
@ -111,14 +111,13 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler)
|
||||||
// InstrumentHandlerTimeToWriteHeader is a middleware that wraps the provided
|
// InstrumentHandlerTimeToWriteHeader is a middleware that wraps the provided
|
||||||
// http.Handler to observe with the provided ObserverVec the request duration
|
// http.Handler to observe with the provided ObserverVec the request duration
|
||||||
// until the response headers are written. The ObserverVec must have zero, one,
|
// until the response headers are written. The ObserverVec must have zero, one,
|
||||||
// or two labels. The only allowed label names are "code" and "method". The
|
// or two non-const non-curried labels. For those, the only allowed label names
|
||||||
// function panics if any other instance labels are provided. The Observe
|
// are "code" and "method". The function panics otherwise. The Observe method of
|
||||||
// method of the Observer in the ObserverVec is called with the request
|
// the Observer in the ObserverVec is called with the request duration in
|
||||||
// duration in seconds. Partitioning happens by HTTP status code and/or HTTP
|
// seconds. Partitioning happens by HTTP status code and/or HTTP method if the
|
||||||
// method if the respective instance label names are present in the
|
// respective instance label names are present in the ObserverVec. For
|
||||||
// ObserverVec. For unpartitioned observations, use an ObserverVec with zero
|
// unpartitioned observations, use an ObserverVec with zero labels. Note that
|
||||||
// labels. Note that partitioning of Histograms is expensive and should be used
|
// partitioning of Histograms is expensive and should be used judiciously.
|
||||||
// judiciously.
|
|
||||||
//
|
//
|
||||||
// If the wrapped Handler panics before calling WriteHeader, no value is
|
// If the wrapped Handler panics before calling WriteHeader, no value is
|
||||||
// reported.
|
// reported.
|
||||||
|
@ -140,15 +139,15 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstrumentHandlerRequestSize is a middleware that wraps the provided
|
// InstrumentHandlerRequestSize is a middleware that wraps the provided
|
||||||
// http.Handler to observe the request size with the provided ObserverVec.
|
// http.Handler to observe the request size with the provided ObserverVec. The
|
||||||
// The ObserverVec must have zero, one, or two labels. The only allowed label
|
// ObserverVec must have zero, one, or two non-const non-curried labels. For
|
||||||
// names are "code" and "method". The function panics if any other instance
|
// those, the only allowed label names are "code" and "method". The function
|
||||||
// labels are provided. The Observe method of the Observer in the ObserverVec
|
// panics otherwise. The Observe method of the Observer in the ObserverVec is
|
||||||
// is called with the request size in bytes. Partitioning happens by HTTP
|
// called with the request size in bytes. Partitioning happens by HTTP status
|
||||||
// status code and/or HTTP method if the respective instance label names are
|
// code and/or HTTP method if the respective instance label names are present in
|
||||||
// present in the ObserverVec. For unpartitioned observations, use an
|
// the ObserverVec. For unpartitioned observations, use an ObserverVec with zero
|
||||||
// ObserverVec with zero labels. Note that partitioning of Histograms is
|
// labels. Note that partitioning of Histograms is expensive and should be used
|
||||||
// expensive and should be used judiciously.
|
// judiciously.
|
||||||
//
|
//
|
||||||
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
|
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
|
||||||
//
|
//
|
||||||
|
@ -175,15 +174,15 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstrumentHandlerResponseSize is a middleware that wraps the provided
|
// InstrumentHandlerResponseSize is a middleware that wraps the provided
|
||||||
// http.Handler to observe the response size with the provided ObserverVec.
|
// http.Handler to observe the response size with the provided ObserverVec. The
|
||||||
// The ObserverVec must have zero, one, or two labels. The only allowed label
|
// ObserverVec must have zero, one, or two non-const non-curried labels. For
|
||||||
// names are "code" and "method". The function panics if any other instance
|
// those, the only allowed label names are "code" and "method". The function
|
||||||
// labels are provided. The Observe method of the Observer in the ObserverVec
|
// panics otherwise. The Observe method of the Observer in the ObserverVec is
|
||||||
// is called with the response size in bytes. Partitioning happens by HTTP
|
// called with the response size in bytes. Partitioning happens by HTTP status
|
||||||
// status code and/or HTTP method if the respective instance label names are
|
// code and/or HTTP method if the respective instance label names are present in
|
||||||
// present in the ObserverVec. For unpartitioned observations, use an
|
// the ObserverVec. For unpartitioned observations, use an ObserverVec with zero
|
||||||
// ObserverVec with zero labels. Note that partitioning of Histograms is
|
// labels. Note that partitioning of Histograms is expensive and should be used
|
||||||
// expensive and should be used judiciously.
|
// judiciously.
|
||||||
//
|
//
|
||||||
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
|
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
|
||||||
//
|
//
|
||||||
|
@ -204,9 +203,12 @@ func checkLabels(c prometheus.Collector) (code bool, method bool) {
|
||||||
// once Descriptors can have their dimensionality queried.
|
// once Descriptors can have their dimensionality queried.
|
||||||
var (
|
var (
|
||||||
desc *prometheus.Desc
|
desc *prometheus.Desc
|
||||||
|
m prometheus.Metric
|
||||||
pm dto.Metric
|
pm dto.Metric
|
||||||
|
lvs []string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Get the Desc from the Collector.
|
||||||
descc := make(chan *prometheus.Desc, 1)
|
descc := make(chan *prometheus.Desc, 1)
|
||||||
c.Describe(descc)
|
c.Describe(descc)
|
||||||
|
|
||||||
|
@ -223,16 +225,22 @@ func checkLabels(c prometheus.Collector) (code bool, method bool) {
|
||||||
|
|
||||||
close(descc)
|
close(descc)
|
||||||
|
|
||||||
if _, err := prometheus.NewConstMetric(desc, prometheus.UntypedValue, 0); err == nil {
|
// Create a ConstMetric with the Desc. Since we don't know how many
|
||||||
return
|
// variable labels there are, try for as long as it needs.
|
||||||
|
for err := errors.New("dummy"); err != nil; lvs = append(lvs, magicString) {
|
||||||
|
m, err = prometheus.NewConstMetric(desc, prometheus.UntypedValue, 0, lvs...)
|
||||||
}
|
}
|
||||||
if m, err := prometheus.NewConstMetric(desc, prometheus.UntypedValue, 0, magicString); err == nil {
|
|
||||||
|
// Write out the metric into a proto message and look at the labels.
|
||||||
|
// If the value is not the magicString, it is a constLabel, which doesn't interest us.
|
||||||
|
// If the label is curried, it doesn't interest us.
|
||||||
|
// In all other cases, only "code" or "method" is allowed.
|
||||||
if err := m.Write(&pm); err != nil {
|
if err := m.Write(&pm); err != nil {
|
||||||
panic("error checking metric for labels")
|
panic("error checking metric for labels")
|
||||||
}
|
}
|
||||||
for _, label := range pm.Label {
|
for _, label := range pm.Label {
|
||||||
name, value := label.GetName(), label.GetValue()
|
name, value := label.GetName(), label.GetValue()
|
||||||
if value != magicString {
|
if value != magicString || isLabelCurried(c, name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
switch name {
|
switch name {
|
||||||
|
@ -243,29 +251,28 @@ func checkLabels(c prometheus.Collector) (code bool, method bool) {
|
||||||
default:
|
default:
|
||||||
panic("metric partitioned with non-supported labels")
|
panic("metric partitioned with non-supported labels")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func isLabelCurried(c prometheus.Collector, label string) bool {
|
||||||
|
// This is even hackier than the label test above.
|
||||||
|
// We essentially try to curry again and see if it works.
|
||||||
|
// But for that, we need to type-convert to the two
|
||||||
|
// types we use here, ObserverVec or *CounterVec.
|
||||||
|
switch v := c.(type) {
|
||||||
|
case *prometheus.CounterVec:
|
||||||
|
if _, err := v.CurryWith(prometheus.Labels{label: "dummy"}); err == nil {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
panic("previously set label not found – this must never happen")
|
case prometheus.ObserverVec:
|
||||||
|
if _, err := v.CurryWith(prometheus.Labels{label: "dummy"}); err == nil {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
if m, err := prometheus.NewConstMetric(desc, prometheus.UntypedValue, 0, magicString, magicString); err == nil {
|
default:
|
||||||
if err := m.Write(&pm); err != nil {
|
panic("unsupported metric vec type")
|
||||||
panic("error checking metric for labels")
|
|
||||||
}
|
}
|
||||||
for _, label := range pm.Label {
|
return true
|
||||||
name, value := label.GetName(), label.GetValue()
|
|
||||||
if value != magicString {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if name == "code" || name == "method" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
panic("metric partitioned with non-supported labels")
|
|
||||||
}
|
|
||||||
code = true
|
|
||||||
method = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
panic("metric partitioned with non-supported labels")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// emptyLabels is a one-time allocation for non-partitioned metrics to avoid
|
// emptyLabels is a one-time allocation for non-partitioned metrics to avoid
|
||||||
|
|
|
@ -656,7 +656,7 @@ func normalizeMetricFamilies(metricFamiliesByName map[string]*dto.MetricFamily)
|
||||||
|
|
||||||
// checkMetricConsistency checks if the provided Metric is consistent with the
|
// checkMetricConsistency checks if the provided Metric is consistent with the
|
||||||
// provided MetricFamily. It also hashed the Metric labels and the MetricFamily
|
// provided MetricFamily. It also hashed the Metric labels and the MetricFamily
|
||||||
// name. If the resulting hash is alread in the provided metricHashes, an error
|
// name. If the resulting hash is already in the provided metricHashes, an error
|
||||||
// is returned. If not, it is added to metricHashes. The provided dimHashes maps
|
// is returned. If not, it is added to metricHashes. The provided dimHashes maps
|
||||||
// MetricFamily names to their dimHash (hashed sorted label names). If dimHashes
|
// MetricFamily names to their dimHash (hashed sorted label names). If dimHashes
|
||||||
// doesn't yet contain a hash for the provided MetricFamily, it is
|
// doesn't yet contain a hash for the provided MetricFamily, it is
|
||||||
|
|
|
@ -36,7 +36,10 @@ const quantileLabel = "quantile"
|
||||||
//
|
//
|
||||||
// A typical use-case is the observation of request latencies. By default, a
|
// A typical use-case is the observation of request latencies. By default, a
|
||||||
// Summary provides the median, the 90th and the 99th percentile of the latency
|
// Summary provides the median, the 90th and the 99th percentile of the latency
|
||||||
// as rank estimations.
|
// as rank estimations. However, the default behavior will change in the
|
||||||
|
// upcoming v0.10 of the library. There will be no rank estiamtions at all by
|
||||||
|
// default. For a sane transition, it is recommended to set the desired rank
|
||||||
|
// estimations explicitly.
|
||||||
//
|
//
|
||||||
// Note that the rank estimations cannot be aggregated in a meaningful way with
|
// Note that the rank estimations cannot be aggregated in a meaningful way with
|
||||||
// the Prometheus query language (i.e. you cannot average or add them). If you
|
// the Prometheus query language (i.e. you cannot average or add them). If you
|
||||||
|
@ -78,8 +81,10 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// SummaryOpts bundles the options for creating a Summary metric. It is
|
// SummaryOpts bundles the options for creating a Summary metric. It is
|
||||||
// mandatory to set Name and Help to a non-empty string. All other fields are
|
// mandatory to set Name and Help to a non-empty string. While all other fields
|
||||||
// optional and can safely be left at their zero value.
|
// are optional and can safely be left at their zero value, it is recommended to
|
||||||
|
// explicitly set the Objectives field to the desired value as the default value
|
||||||
|
// will change in the upcoming v0.10 of the library.
|
||||||
type SummaryOpts struct {
|
type SummaryOpts struct {
|
||||||
// Namespace, Subsystem, and Name are components of the fully-qualified
|
// Namespace, Subsystem, and Name are components of the fully-qualified
|
||||||
// name of the Summary (created by joining these components with
|
// name of the Summary (created by joining these components with
|
||||||
|
@ -96,23 +101,16 @@ type SummaryOpts struct {
|
||||||
// string.
|
// string.
|
||||||
Help string
|
Help string
|
||||||
|
|
||||||
// ConstLabels are used to attach fixed labels to this
|
// ConstLabels are used to attach fixed labels to this metric. Metrics
|
||||||
// Summary. Summaries with the same fully-qualified name must have the
|
// with the same fully-qualified name must have the same label names in
|
||||||
// same label names in their ConstLabels.
|
// their ConstLabels.
|
||||||
//
|
//
|
||||||
// Note that in most cases, labels have a value that varies during the
|
// ConstLabels are only used rarely. In particular, do not use them to
|
||||||
// lifetime of a process. Those labels are usually managed with a
|
// attach the same labels to all your metrics. Those use cases are
|
||||||
// SummaryVec. ConstLabels serve only special purposes. One is for the
|
// better covered by target labels set by the scraping Prometheus
|
||||||
// special case where the value of a label does not change during the
|
// server, or by one specific metric (e.g. a build_info or a
|
||||||
// lifetime of a process, e.g. if the revision of the running binary is
|
// machine_role metric). See also
|
||||||
// put into a label. Another, more advanced purpose is if more than one
|
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
|
||||||
// Collector needs to collect Summaries with the same fully-qualified
|
|
||||||
// name. In that case, those Summaries must differ in the values of
|
|
||||||
// their ConstLabels. See the Collector examples.
|
|
||||||
//
|
|
||||||
// If the value of a label never changes (not even between binaries),
|
|
||||||
// that label most likely should not be a label at all (but part of the
|
|
||||||
// metric name).
|
|
||||||
ConstLabels Labels
|
ConstLabels Labels
|
||||||
|
|
||||||
// Objectives defines the quantile rank estimates with their respective
|
// Objectives defines the quantile rank estimates with their respective
|
||||||
|
@ -428,13 +426,13 @@ func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
|
||||||
//
|
//
|
||||||
// Keeping the Summary for later use is possible (and should be considered if
|
// Keeping the Summary for later use is possible (and should be considered if
|
||||||
// performance is critical), but keep in mind that Reset, DeleteLabelValues and
|
// performance is critical), but keep in mind that Reset, DeleteLabelValues and
|
||||||
// Delete can be used to delete the Summary from the SummaryVec. In that case, the
|
// Delete can be used to delete the Summary from the SummaryVec. In that case,
|
||||||
// Summary will still exist, but it will not be exported anymore, even if a
|
// the Summary will still exist, but it will not be exported anymore, even if a
|
||||||
// Summary with the same label values is created later. See also the CounterVec
|
// Summary with the same label values is created later. See also the CounterVec
|
||||||
// example.
|
// example.
|
||||||
//
|
//
|
||||||
// An error is returned if the number of label values is not the same as the
|
// An error is returned if the number of label values is not the same as the
|
||||||
// number of VariableLabels in Desc.
|
// number of VariableLabels in Desc (minus any curried labels).
|
||||||
//
|
//
|
||||||
// Note that for more than one label value, this method is prone to mistakes
|
// Note that for more than one label value, this method is prone to mistakes
|
||||||
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
|
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
|
||||||
|
@ -442,8 +440,8 @@ func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
|
||||||
// latter has a much more readable (albeit more verbose) syntax, but it comes
|
// latter has a much more readable (albeit more verbose) syntax, but it comes
|
||||||
// with a performance overhead (for creating and processing the Labels map).
|
// with a performance overhead (for creating and processing the Labels map).
|
||||||
// See also the GaugeVec example.
|
// See also the GaugeVec example.
|
||||||
func (m *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
|
func (v *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
|
||||||
metric, err := m.metricVec.getMetricWithLabelValues(lvs...)
|
metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
|
||||||
if metric != nil {
|
if metric != nil {
|
||||||
return metric.(Observer), err
|
return metric.(Observer), err
|
||||||
}
|
}
|
||||||
|
@ -457,13 +455,13 @@ func (m *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
|
||||||
// the same as for GetMetricWithLabelValues.
|
// the same as for GetMetricWithLabelValues.
|
||||||
//
|
//
|
||||||
// An error is returned if the number and names of the Labels are inconsistent
|
// An error is returned if the number and names of the Labels are inconsistent
|
||||||
// with those of the VariableLabels in Desc.
|
// with those of the VariableLabels in Desc (minus any curried labels).
|
||||||
//
|
//
|
||||||
// This method is used for the same purpose as
|
// This method is used for the same purpose as
|
||||||
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
||||||
// methods.
|
// methods.
|
||||||
func (m *SummaryVec) GetMetricWith(labels Labels) (Observer, error) {
|
func (v *SummaryVec) GetMetricWith(labels Labels) (Observer, error) {
|
||||||
metric, err := m.metricVec.getMetricWith(labels)
|
metric, err := v.metricVec.getMetricWith(labels)
|
||||||
if metric != nil {
|
if metric != nil {
|
||||||
return metric.(Observer), err
|
return metric.(Observer), err
|
||||||
}
|
}
|
||||||
|
@ -471,18 +469,57 @@ func (m *SummaryVec) GetMetricWith(labels Labels) (Observer, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithLabelValues works as GetMetricWithLabelValues, but panics where
|
// WithLabelValues works as GetMetricWithLabelValues, but panics where
|
||||||
// GetMetricWithLabelValues would have returned an error. By not returning an
|
// GetMetricWithLabelValues would have returned an error. Not returning an
|
||||||
// error, WithLabelValues allows shortcuts like
|
// error allows shortcuts like
|
||||||
// myVec.WithLabelValues("404", "GET").Observe(42.21)
|
// myVec.WithLabelValues("404", "GET").Observe(42.21)
|
||||||
func (m *SummaryVec) WithLabelValues(lvs ...string) Observer {
|
func (v *SummaryVec) WithLabelValues(lvs ...string) Observer {
|
||||||
return m.metricVec.withLabelValues(lvs...).(Observer)
|
s, err := v.GetMetricWithLabelValues(lvs...)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// With works as GetMetricWith, but panics where GetMetricWithLabels would have
|
// With works as GetMetricWith, but panics where GetMetricWithLabels would have
|
||||||
// returned an error. By not returning an error, With allows shortcuts like
|
// returned an error. Not returning an error allows shortcuts like
|
||||||
// myVec.With(Labels{"code": "404", "method": "GET"}).Observe(42.21)
|
// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21)
|
||||||
func (m *SummaryVec) With(labels Labels) Observer {
|
func (v *SummaryVec) With(labels Labels) Observer {
|
||||||
return m.metricVec.with(labels).(Observer)
|
s, err := v.GetMetricWith(labels)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurryWith returns a vector curried with the provided labels, i.e. the
|
||||||
|
// returned vector has those labels pre-set for all labeled operations performed
|
||||||
|
// on it. The cardinality of the curried vector is reduced accordingly. The
|
||||||
|
// order of the remaining labels stays the same (just with the curried labels
|
||||||
|
// taken out of the sequence – which is relevant for the
|
||||||
|
// (GetMetric)WithLabelValues methods). It is possible to curry a curried
|
||||||
|
// vector, but only with labels not yet used for currying before.
|
||||||
|
//
|
||||||
|
// The metrics contained in the SummaryVec are shared between the curried and
|
||||||
|
// uncurried vectors. They are just accessed differently. Curried and uncurried
|
||||||
|
// vectors behave identically in terms of collection. Only one must be
|
||||||
|
// registered with a given registry (usually the uncurried version). The Reset
|
||||||
|
// method deletes all metrics, even if called on a curried vector.
|
||||||
|
func (v *SummaryVec) CurryWith(labels Labels) (ObserverVec, error) {
|
||||||
|
vec, err := v.curryWith(labels)
|
||||||
|
if vec != nil {
|
||||||
|
return &SummaryVec{vec}, err
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustCurryWith works as CurryWith but panics where CurryWith would have
|
||||||
|
// returned an error.
|
||||||
|
func (v *SummaryVec) MustCurryWith(labels Labels) ObserverVec {
|
||||||
|
vec, err := v.CurryWith(labels)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return vec
|
||||||
}
|
}
|
||||||
|
|
||||||
type constSummary struct {
|
type constSummary struct {
|
||||||
|
|
|
@ -15,10 +15,7 @@ package prometheus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"sort"
|
"sort"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
|
@ -36,79 +33,6 @@ const (
|
||||||
UntypedValue
|
UntypedValue
|
||||||
)
|
)
|
||||||
|
|
||||||
// value is a generic metric for simple values. It implements Metric, Collector,
|
|
||||||
// Counter, Gauge, and Untyped. Its effective type is determined by
|
|
||||||
// ValueType. This is a low-level building block used by the library to back the
|
|
||||||
// implementations of Counter, Gauge, and Untyped.
|
|
||||||
type value struct {
|
|
||||||
// valBits contains the bits of the represented float64 value. It has
|
|
||||||
// to go first in the struct to guarantee alignment for atomic
|
|
||||||
// operations. http://golang.org/pkg/sync/atomic/#pkg-note-BUG
|
|
||||||
valBits uint64
|
|
||||||
|
|
||||||
selfCollector
|
|
||||||
|
|
||||||
desc *Desc
|
|
||||||
valType ValueType
|
|
||||||
labelPairs []*dto.LabelPair
|
|
||||||
}
|
|
||||||
|
|
||||||
// newValue returns a newly allocated value with the given Desc, ValueType,
|
|
||||||
// sample value and label values. It panics if the number of label
|
|
||||||
// values is different from the number of variable labels in Desc.
|
|
||||||
func newValue(desc *Desc, valueType ValueType, val float64, labelValues ...string) *value {
|
|
||||||
if len(labelValues) != len(desc.variableLabels) {
|
|
||||||
panic(errInconsistentCardinality)
|
|
||||||
}
|
|
||||||
result := &value{
|
|
||||||
desc: desc,
|
|
||||||
valType: valueType,
|
|
||||||
valBits: math.Float64bits(val),
|
|
||||||
labelPairs: makeLabelPairs(desc, labelValues),
|
|
||||||
}
|
|
||||||
result.init(result)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *value) Desc() *Desc {
|
|
||||||
return v.desc
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *value) Set(val float64) {
|
|
||||||
atomic.StoreUint64(&v.valBits, math.Float64bits(val))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *value) SetToCurrentTime() {
|
|
||||||
v.Set(float64(time.Now().UnixNano()) / 1e9)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *value) Inc() {
|
|
||||||
v.Add(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *value) Dec() {
|
|
||||||
v.Add(-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *value) Add(val float64) {
|
|
||||||
for {
|
|
||||||
oldBits := atomic.LoadUint64(&v.valBits)
|
|
||||||
newBits := math.Float64bits(math.Float64frombits(oldBits) + val)
|
|
||||||
if atomic.CompareAndSwapUint64(&v.valBits, oldBits, newBits) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *value) Sub(val float64) {
|
|
||||||
v.Add(val * -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *value) Write(out *dto.Metric) error {
|
|
||||||
val := math.Float64frombits(atomic.LoadUint64(&v.valBits))
|
|
||||||
return populateMetric(v.valType, val, v.labelPairs, out)
|
|
||||||
}
|
|
||||||
|
|
||||||
// valueFunc is a generic metric for simple values retrieved on collect time
|
// valueFunc is a generic metric for simple values retrieved on collect time
|
||||||
// from a function. It implements Metric and Collector. Its effective type is
|
// from a function. It implements Metric and Collector. Its effective type is
|
||||||
// determined by ValueType. This is a low-level building block used by the
|
// determined by ValueType. This is a low-level building block used by the
|
||||||
|
|
|
@ -23,88 +23,31 @@ import (
|
||||||
// metricVec is a Collector to bundle metrics of the same name that differ in
|
// metricVec is a Collector to bundle metrics of the same name that differ in
|
||||||
// their label values. metricVec is not used directly (and therefore
|
// their label values. metricVec is not used directly (and therefore
|
||||||
// unexported). It is used as a building block for implementations of vectors of
|
// unexported). It is used as a building block for implementations of vectors of
|
||||||
// a given metric type, like GaugeVec, CounterVec, SummaryVec, HistogramVec, and
|
// a given metric type, like GaugeVec, CounterVec, SummaryVec, and HistogramVec.
|
||||||
// UntypedVec.
|
// It also handles label currying. It uses basicMetricVec internally.
|
||||||
type metricVec struct {
|
type metricVec struct {
|
||||||
mtx sync.RWMutex // Protects the children.
|
*metricMap
|
||||||
children map[uint64][]metricWithLabelValues
|
|
||||||
desc *Desc
|
|
||||||
|
|
||||||
newMetric func(labelValues ...string) Metric
|
curry []curriedLabelValue
|
||||||
hashAdd func(h uint64, s string) uint64 // replace hash function for testing collision handling
|
|
||||||
|
// hashAdd and hashAddByte can be replaced for testing collision handling.
|
||||||
|
hashAdd func(h uint64, s string) uint64
|
||||||
hashAddByte func(h uint64, b byte) uint64
|
hashAddByte func(h uint64, b byte) uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// newMetricVec returns an initialized metricVec.
|
// newMetricVec returns an initialized metricVec.
|
||||||
func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *metricVec {
|
func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *metricVec {
|
||||||
return &metricVec{
|
return &metricVec{
|
||||||
children: map[uint64][]metricWithLabelValues{},
|
metricMap: &metricMap{
|
||||||
|
metrics: map[uint64][]metricWithLabelValues{},
|
||||||
desc: desc,
|
desc: desc,
|
||||||
newMetric: newMetric,
|
newMetric: newMetric,
|
||||||
|
},
|
||||||
hashAdd: hashAdd,
|
hashAdd: hashAdd,
|
||||||
hashAddByte: hashAddByte,
|
hashAddByte: hashAddByte,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// metricWithLabelValues provides the metric and its label values for
|
|
||||||
// disambiguation on hash collision.
|
|
||||||
type metricWithLabelValues struct {
|
|
||||||
values []string
|
|
||||||
metric Metric
|
|
||||||
}
|
|
||||||
|
|
||||||
// Describe implements Collector. The length of the returned slice
|
|
||||||
// is always one.
|
|
||||||
func (m *metricVec) Describe(ch chan<- *Desc) {
|
|
||||||
ch <- m.desc
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect implements Collector.
|
|
||||||
func (m *metricVec) Collect(ch chan<- Metric) {
|
|
||||||
m.mtx.RLock()
|
|
||||||
defer m.mtx.RUnlock()
|
|
||||||
|
|
||||||
for _, metrics := range m.children {
|
|
||||||
for _, metric := range metrics {
|
|
||||||
ch <- metric.metric
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *metricVec) getMetricWithLabelValues(lvs ...string) (Metric, error) {
|
|
||||||
h, err := m.hashLabelValues(lvs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.getOrCreateMetricWithLabelValues(h, lvs), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *metricVec) getMetricWith(labels Labels) (Metric, error) {
|
|
||||||
h, err := m.hashLabels(labels)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.getOrCreateMetricWithLabels(h, labels), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *metricVec) withLabelValues(lvs ...string) Metric {
|
|
||||||
metric, err := m.getMetricWithLabelValues(lvs...)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return metric
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *metricVec) with(labels Labels) Metric {
|
|
||||||
metric, err := m.getMetricWith(labels)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return metric
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteLabelValues removes the metric where the variable labels are the same
|
// DeleteLabelValues removes the metric where the variable labels are the same
|
||||||
// as those passed in as labels (same order as the VariableLabels in Desc). It
|
// as those passed in as labels (same order as the VariableLabels in Desc). It
|
||||||
// returns true if a metric was deleted.
|
// returns true if a metric was deleted.
|
||||||
|
@ -121,14 +64,12 @@ func (m *metricVec) with(labels Labels) Metric {
|
||||||
// with a performance overhead (for creating and processing the Labels map).
|
// with a performance overhead (for creating and processing the Labels map).
|
||||||
// See also the CounterVec example.
|
// See also the CounterVec example.
|
||||||
func (m *metricVec) DeleteLabelValues(lvs ...string) bool {
|
func (m *metricVec) DeleteLabelValues(lvs ...string) bool {
|
||||||
m.mtx.Lock()
|
|
||||||
defer m.mtx.Unlock()
|
|
||||||
|
|
||||||
h, err := m.hashLabelValues(lvs)
|
h, err := m.hashLabelValues(lvs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return m.deleteByHashWithLabelValues(h, lvs)
|
|
||||||
|
return m.metricMap.deleteByHashWithLabelValues(h, lvs, m.curry)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete deletes the metric where the variable labels are the same as those
|
// Delete deletes the metric where the variable labels are the same as those
|
||||||
|
@ -142,35 +83,190 @@ func (m *metricVec) DeleteLabelValues(lvs ...string) bool {
|
||||||
// This method is used for the same purpose as DeleteLabelValues(...string). See
|
// This method is used for the same purpose as DeleteLabelValues(...string). See
|
||||||
// there for pros and cons of the two methods.
|
// there for pros and cons of the two methods.
|
||||||
func (m *metricVec) Delete(labels Labels) bool {
|
func (m *metricVec) Delete(labels Labels) bool {
|
||||||
m.mtx.Lock()
|
|
||||||
defer m.mtx.Unlock()
|
|
||||||
|
|
||||||
h, err := m.hashLabels(labels)
|
h, err := m.hashLabels(labels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.deleteByHashWithLabels(h, labels)
|
return m.metricMap.deleteByHashWithLabels(h, labels, m.curry)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metricVec) curryWith(labels Labels) (*metricVec, error) {
|
||||||
|
var (
|
||||||
|
newCurry []curriedLabelValue
|
||||||
|
oldCurry = m.curry
|
||||||
|
iCurry int
|
||||||
|
)
|
||||||
|
for i, label := range m.desc.variableLabels {
|
||||||
|
val, ok := labels[label]
|
||||||
|
if iCurry < len(oldCurry) && oldCurry[iCurry].index == i {
|
||||||
|
if ok {
|
||||||
|
return nil, fmt.Errorf("label name %q is already curried", label)
|
||||||
|
}
|
||||||
|
newCurry = append(newCurry, oldCurry[iCurry])
|
||||||
|
iCurry++
|
||||||
|
} else {
|
||||||
|
if !ok {
|
||||||
|
continue // Label stays uncurried.
|
||||||
|
}
|
||||||
|
newCurry = append(newCurry, curriedLabelValue{i, val})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if l := len(oldCurry) + len(labels) - len(newCurry); l > 0 {
|
||||||
|
return nil, fmt.Errorf("%d unknown label(s) found during currying", l)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &metricVec{
|
||||||
|
metricMap: m.metricMap,
|
||||||
|
curry: newCurry,
|
||||||
|
hashAdd: m.hashAdd,
|
||||||
|
hashAddByte: m.hashAddByte,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metricVec) getMetricWithLabelValues(lvs ...string) (Metric, error) {
|
||||||
|
h, err := m.hashLabelValues(lvs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.metricMap.getOrCreateMetricWithLabelValues(h, lvs, m.curry), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metricVec) getMetricWith(labels Labels) (Metric, error) {
|
||||||
|
h, err := m.hashLabels(labels)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.metricMap.getOrCreateMetricWithLabels(h, labels, m.curry), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metricVec) hashLabelValues(vals []string) (uint64, error) {
|
||||||
|
if err := validateLabelValues(vals, len(m.desc.variableLabels)-len(m.curry)); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
h = hashNew()
|
||||||
|
curry = m.curry
|
||||||
|
iVals, iCurry int
|
||||||
|
)
|
||||||
|
for i := 0; i < len(m.desc.variableLabels); i++ {
|
||||||
|
if iCurry < len(curry) && curry[iCurry].index == i {
|
||||||
|
h = m.hashAdd(h, curry[iCurry].value)
|
||||||
|
iCurry++
|
||||||
|
} else {
|
||||||
|
h = m.hashAdd(h, vals[iVals])
|
||||||
|
iVals++
|
||||||
|
}
|
||||||
|
h = m.hashAddByte(h, model.SeparatorByte)
|
||||||
|
}
|
||||||
|
return h, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metricVec) hashLabels(labels Labels) (uint64, error) {
|
||||||
|
if err := validateValuesInLabels(labels, len(m.desc.variableLabels)-len(m.curry)); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
h = hashNew()
|
||||||
|
curry = m.curry
|
||||||
|
iCurry int
|
||||||
|
)
|
||||||
|
for i, label := range m.desc.variableLabels {
|
||||||
|
val, ok := labels[label]
|
||||||
|
if iCurry < len(curry) && curry[iCurry].index == i {
|
||||||
|
if ok {
|
||||||
|
return 0, fmt.Errorf("label name %q is already curried", label)
|
||||||
|
}
|
||||||
|
h = m.hashAdd(h, curry[iCurry].value)
|
||||||
|
iCurry++
|
||||||
|
} else {
|
||||||
|
if !ok {
|
||||||
|
return 0, fmt.Errorf("label name %q missing in label map", label)
|
||||||
|
}
|
||||||
|
h = m.hashAdd(h, val)
|
||||||
|
}
|
||||||
|
h = m.hashAddByte(h, model.SeparatorByte)
|
||||||
|
}
|
||||||
|
return h, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// metricWithLabelValues provides the metric and its label values for
|
||||||
|
// disambiguation on hash collision.
|
||||||
|
type metricWithLabelValues struct {
|
||||||
|
values []string
|
||||||
|
metric Metric
|
||||||
|
}
|
||||||
|
|
||||||
|
// curriedLabelValue sets the curried value for a label at the given index.
|
||||||
|
type curriedLabelValue struct {
|
||||||
|
index int
|
||||||
|
value string
|
||||||
|
}
|
||||||
|
|
||||||
|
// metricMap is a helper for metricVec and shared between differently curried
|
||||||
|
// metricVecs.
|
||||||
|
type metricMap struct {
|
||||||
|
mtx sync.RWMutex // Protects metrics.
|
||||||
|
metrics map[uint64][]metricWithLabelValues
|
||||||
|
desc *Desc
|
||||||
|
newMetric func(labelValues ...string) Metric
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describe implements Collector. It will send exactly one Desc to the provided
|
||||||
|
// channel.
|
||||||
|
func (m *metricMap) Describe(ch chan<- *Desc) {
|
||||||
|
ch <- m.desc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect implements Collector.
|
||||||
|
func (m *metricMap) Collect(ch chan<- Metric) {
|
||||||
|
m.mtx.RLock()
|
||||||
|
defer m.mtx.RUnlock()
|
||||||
|
|
||||||
|
for _, metrics := range m.metrics {
|
||||||
|
for _, metric := range metrics {
|
||||||
|
ch <- metric.metric
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset deletes all metrics in this vector.
|
||||||
|
func (m *metricMap) Reset() {
|
||||||
|
m.mtx.Lock()
|
||||||
|
defer m.mtx.Unlock()
|
||||||
|
|
||||||
|
for h := range m.metrics {
|
||||||
|
delete(m.metrics, h)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// deleteByHashWithLabelValues removes the metric from the hash bucket h. If
|
// deleteByHashWithLabelValues removes the metric from the hash bucket h. If
|
||||||
// there are multiple matches in the bucket, use lvs to select a metric and
|
// there are multiple matches in the bucket, use lvs to select a metric and
|
||||||
// remove only that metric.
|
// remove only that metric.
|
||||||
func (m *metricVec) deleteByHashWithLabelValues(h uint64, lvs []string) bool {
|
func (m *metricMap) deleteByHashWithLabelValues(
|
||||||
metrics, ok := m.children[h]
|
h uint64, lvs []string, curry []curriedLabelValue,
|
||||||
|
) bool {
|
||||||
|
m.mtx.Lock()
|
||||||
|
defer m.mtx.Unlock()
|
||||||
|
|
||||||
|
metrics, ok := m.metrics[h]
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
i := m.findMetricWithLabelValues(metrics, lvs)
|
i := findMetricWithLabelValues(metrics, lvs, curry)
|
||||||
if i >= len(metrics) {
|
if i >= len(metrics) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(metrics) > 1 {
|
if len(metrics) > 1 {
|
||||||
m.children[h] = append(metrics[:i], metrics[i+1:]...)
|
m.metrics[h] = append(metrics[:i], metrics[i+1:]...)
|
||||||
} else {
|
} else {
|
||||||
delete(m.children, h)
|
delete(m.metrics, h)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -178,71 +274,35 @@ func (m *metricVec) deleteByHashWithLabelValues(h uint64, lvs []string) bool {
|
||||||
// deleteByHashWithLabels removes the metric from the hash bucket h. If there
|
// deleteByHashWithLabels removes the metric from the hash bucket h. If there
|
||||||
// are multiple matches in the bucket, use lvs to select a metric and remove
|
// are multiple matches in the bucket, use lvs to select a metric and remove
|
||||||
// only that metric.
|
// only that metric.
|
||||||
func (m *metricVec) deleteByHashWithLabels(h uint64, labels Labels) bool {
|
func (m *metricMap) deleteByHashWithLabels(
|
||||||
metrics, ok := m.children[h]
|
h uint64, labels Labels, curry []curriedLabelValue,
|
||||||
|
) bool {
|
||||||
|
metrics, ok := m.metrics[h]
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
i := m.findMetricWithLabels(metrics, labels)
|
i := findMetricWithLabels(m.desc, metrics, labels, curry)
|
||||||
if i >= len(metrics) {
|
if i >= len(metrics) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(metrics) > 1 {
|
if len(metrics) > 1 {
|
||||||
m.children[h] = append(metrics[:i], metrics[i+1:]...)
|
m.metrics[h] = append(metrics[:i], metrics[i+1:]...)
|
||||||
} else {
|
} else {
|
||||||
delete(m.children, h)
|
delete(m.metrics, h)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset deletes all metrics in this vector.
|
|
||||||
func (m *metricVec) Reset() {
|
|
||||||
m.mtx.Lock()
|
|
||||||
defer m.mtx.Unlock()
|
|
||||||
|
|
||||||
for h := range m.children {
|
|
||||||
delete(m.children, h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *metricVec) hashLabelValues(vals []string) (uint64, error) {
|
|
||||||
if err := validateLabelValues(vals, len(m.desc.variableLabels)); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
h := hashNew()
|
|
||||||
for _, val := range vals {
|
|
||||||
h = m.hashAdd(h, val)
|
|
||||||
h = m.hashAddByte(h, model.SeparatorByte)
|
|
||||||
}
|
|
||||||
return h, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *metricVec) hashLabels(labels Labels) (uint64, error) {
|
|
||||||
if err := validateValuesInLabels(labels, len(m.desc.variableLabels)); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
h := hashNew()
|
|
||||||
for _, label := range m.desc.variableLabels {
|
|
||||||
val, ok := labels[label]
|
|
||||||
if !ok {
|
|
||||||
return 0, fmt.Errorf("label name %q missing in label map", label)
|
|
||||||
}
|
|
||||||
h = m.hashAdd(h, val)
|
|
||||||
h = m.hashAddByte(h, model.SeparatorByte)
|
|
||||||
}
|
|
||||||
return h, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getOrCreateMetricWithLabelValues retrieves the metric by hash and label value
|
// getOrCreateMetricWithLabelValues retrieves the metric by hash and label value
|
||||||
// or creates it and returns the new one.
|
// or creates it and returns the new one.
|
||||||
//
|
//
|
||||||
// This function holds the mutex.
|
// This function holds the mutex.
|
||||||
func (m *metricVec) getOrCreateMetricWithLabelValues(hash uint64, lvs []string) Metric {
|
func (m *metricMap) getOrCreateMetricWithLabelValues(
|
||||||
|
hash uint64, lvs []string, curry []curriedLabelValue,
|
||||||
|
) Metric {
|
||||||
m.mtx.RLock()
|
m.mtx.RLock()
|
||||||
metric, ok := m.getMetricWithHashAndLabelValues(hash, lvs)
|
metric, ok := m.getMetricWithHashAndLabelValues(hash, lvs, curry)
|
||||||
m.mtx.RUnlock()
|
m.mtx.RUnlock()
|
||||||
if ok {
|
if ok {
|
||||||
return metric
|
return metric
|
||||||
|
@ -250,13 +310,11 @@ func (m *metricVec) getOrCreateMetricWithLabelValues(hash uint64, lvs []string)
|
||||||
|
|
||||||
m.mtx.Lock()
|
m.mtx.Lock()
|
||||||
defer m.mtx.Unlock()
|
defer m.mtx.Unlock()
|
||||||
metric, ok = m.getMetricWithHashAndLabelValues(hash, lvs)
|
metric, ok = m.getMetricWithHashAndLabelValues(hash, lvs, curry)
|
||||||
if !ok {
|
if !ok {
|
||||||
// Copy to avoid allocation in case wo don't go down this code path.
|
inlinedLVs := inlineLabelValues(lvs, curry)
|
||||||
copiedLVs := make([]string, len(lvs))
|
metric = m.newMetric(inlinedLVs...)
|
||||||
copy(copiedLVs, lvs)
|
m.metrics[hash] = append(m.metrics[hash], metricWithLabelValues{values: inlinedLVs, metric: metric})
|
||||||
metric = m.newMetric(copiedLVs...)
|
|
||||||
m.children[hash] = append(m.children[hash], metricWithLabelValues{values: copiedLVs, metric: metric})
|
|
||||||
}
|
}
|
||||||
return metric
|
return metric
|
||||||
}
|
}
|
||||||
|
@ -265,9 +323,11 @@ func (m *metricVec) getOrCreateMetricWithLabelValues(hash uint64, lvs []string)
|
||||||
// or creates it and returns the new one.
|
// or creates it and returns the new one.
|
||||||
//
|
//
|
||||||
// This function holds the mutex.
|
// This function holds the mutex.
|
||||||
func (m *metricVec) getOrCreateMetricWithLabels(hash uint64, labels Labels) Metric {
|
func (m *metricMap) getOrCreateMetricWithLabels(
|
||||||
|
hash uint64, labels Labels, curry []curriedLabelValue,
|
||||||
|
) Metric {
|
||||||
m.mtx.RLock()
|
m.mtx.RLock()
|
||||||
metric, ok := m.getMetricWithHashAndLabels(hash, labels)
|
metric, ok := m.getMetricWithHashAndLabels(hash, labels, curry)
|
||||||
m.mtx.RUnlock()
|
m.mtx.RUnlock()
|
||||||
if ok {
|
if ok {
|
||||||
return metric
|
return metric
|
||||||
|
@ -275,21 +335,23 @@ func (m *metricVec) getOrCreateMetricWithLabels(hash uint64, labels Labels) Metr
|
||||||
|
|
||||||
m.mtx.Lock()
|
m.mtx.Lock()
|
||||||
defer m.mtx.Unlock()
|
defer m.mtx.Unlock()
|
||||||
metric, ok = m.getMetricWithHashAndLabels(hash, labels)
|
metric, ok = m.getMetricWithHashAndLabels(hash, labels, curry)
|
||||||
if !ok {
|
if !ok {
|
||||||
lvs := m.extractLabelValues(labels)
|
lvs := extractLabelValues(m.desc, labels, curry)
|
||||||
metric = m.newMetric(lvs...)
|
metric = m.newMetric(lvs...)
|
||||||
m.children[hash] = append(m.children[hash], metricWithLabelValues{values: lvs, metric: metric})
|
m.metrics[hash] = append(m.metrics[hash], metricWithLabelValues{values: lvs, metric: metric})
|
||||||
}
|
}
|
||||||
return metric
|
return metric
|
||||||
}
|
}
|
||||||
|
|
||||||
// getMetricWithHashAndLabelValues gets a metric while handling possible
|
// getMetricWithHashAndLabelValues gets a metric while handling possible
|
||||||
// collisions in the hash space. Must be called while holding the read mutex.
|
// collisions in the hash space. Must be called while holding the read mutex.
|
||||||
func (m *metricVec) getMetricWithHashAndLabelValues(h uint64, lvs []string) (Metric, bool) {
|
func (m *metricMap) getMetricWithHashAndLabelValues(
|
||||||
metrics, ok := m.children[h]
|
h uint64, lvs []string, curry []curriedLabelValue,
|
||||||
|
) (Metric, bool) {
|
||||||
|
metrics, ok := m.metrics[h]
|
||||||
if ok {
|
if ok {
|
||||||
if i := m.findMetricWithLabelValues(metrics, lvs); i < len(metrics) {
|
if i := findMetricWithLabelValues(metrics, lvs, curry); i < len(metrics) {
|
||||||
return metrics[i].metric, true
|
return metrics[i].metric, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,10 +360,12 @@ func (m *metricVec) getMetricWithHashAndLabelValues(h uint64, lvs []string) (Met
|
||||||
|
|
||||||
// getMetricWithHashAndLabels gets a metric while handling possible collisions in
|
// getMetricWithHashAndLabels gets a metric while handling possible collisions in
|
||||||
// the hash space. Must be called while holding read mutex.
|
// the hash space. Must be called while holding read mutex.
|
||||||
func (m *metricVec) getMetricWithHashAndLabels(h uint64, labels Labels) (Metric, bool) {
|
func (m *metricMap) getMetricWithHashAndLabels(
|
||||||
metrics, ok := m.children[h]
|
h uint64, labels Labels, curry []curriedLabelValue,
|
||||||
|
) (Metric, bool) {
|
||||||
|
metrics, ok := m.metrics[h]
|
||||||
if ok {
|
if ok {
|
||||||
if i := m.findMetricWithLabels(metrics, labels); i < len(metrics) {
|
if i := findMetricWithLabels(m.desc, metrics, labels, curry); i < len(metrics) {
|
||||||
return metrics[i].metric, true
|
return metrics[i].metric, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -310,9 +374,11 @@ func (m *metricVec) getMetricWithHashAndLabels(h uint64, labels Labels) (Metric,
|
||||||
|
|
||||||
// findMetricWithLabelValues returns the index of the matching metric or
|
// findMetricWithLabelValues returns the index of the matching metric or
|
||||||
// len(metrics) if not found.
|
// len(metrics) if not found.
|
||||||
func (m *metricVec) findMetricWithLabelValues(metrics []metricWithLabelValues, lvs []string) int {
|
func findMetricWithLabelValues(
|
||||||
|
metrics []metricWithLabelValues, lvs []string, curry []curriedLabelValue,
|
||||||
|
) int {
|
||||||
for i, metric := range metrics {
|
for i, metric := range metrics {
|
||||||
if m.matchLabelValues(metric.values, lvs) {
|
if matchLabelValues(metric.values, lvs, curry) {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -321,32 +387,51 @@ func (m *metricVec) findMetricWithLabelValues(metrics []metricWithLabelValues, l
|
||||||
|
|
||||||
// findMetricWithLabels returns the index of the matching metric or len(metrics)
|
// findMetricWithLabels returns the index of the matching metric or len(metrics)
|
||||||
// if not found.
|
// if not found.
|
||||||
func (m *metricVec) findMetricWithLabels(metrics []metricWithLabelValues, labels Labels) int {
|
func findMetricWithLabels(
|
||||||
|
desc *Desc, metrics []metricWithLabelValues, labels Labels, curry []curriedLabelValue,
|
||||||
|
) int {
|
||||||
for i, metric := range metrics {
|
for i, metric := range metrics {
|
||||||
if m.matchLabels(metric.values, labels) {
|
if matchLabels(desc, metric.values, labels, curry) {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return len(metrics)
|
return len(metrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *metricVec) matchLabelValues(values []string, lvs []string) bool {
|
func matchLabelValues(values []string, lvs []string, curry []curriedLabelValue) bool {
|
||||||
if len(values) != len(lvs) {
|
if len(values) != len(lvs)+len(curry) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
var iLVs, iCurry int
|
||||||
for i, v := range values {
|
for i, v := range values {
|
||||||
if v != lvs[i] {
|
if iCurry < len(curry) && curry[iCurry].index == i {
|
||||||
|
if v != curry[iCurry].value {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
iCurry++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if v != lvs[iLVs] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
iLVs++
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *metricVec) matchLabels(values []string, labels Labels) bool {
|
func matchLabels(desc *Desc, values []string, labels Labels, curry []curriedLabelValue) bool {
|
||||||
if len(labels) != len(values) {
|
if len(values) != len(labels)+len(curry) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for i, k := range m.desc.variableLabels {
|
iCurry := 0
|
||||||
|
for i, k := range desc.variableLabels {
|
||||||
|
if iCurry < len(curry) && curry[iCurry].index == i {
|
||||||
|
if values[i] != curry[iCurry].value {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
iCurry++
|
||||||
|
continue
|
||||||
|
}
|
||||||
if values[i] != labels[k] {
|
if values[i] != labels[k] {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -354,10 +439,31 @@ func (m *metricVec) matchLabels(values []string, labels Labels) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *metricVec) extractLabelValues(labels Labels) []string {
|
func extractLabelValues(desc *Desc, labels Labels, curry []curriedLabelValue) []string {
|
||||||
labelValues := make([]string, len(labels))
|
labelValues := make([]string, len(labels)+len(curry))
|
||||||
for i, k := range m.desc.variableLabels {
|
iCurry := 0
|
||||||
|
for i, k := range desc.variableLabels {
|
||||||
|
if iCurry < len(curry) && curry[iCurry].index == i {
|
||||||
|
labelValues[i] = curry[iCurry].value
|
||||||
|
iCurry++
|
||||||
|
continue
|
||||||
|
}
|
||||||
labelValues[i] = labels[k]
|
labelValues[i] = labels[k]
|
||||||
}
|
}
|
||||||
return labelValues
|
return labelValues
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func inlineLabelValues(lvs []string, curry []curriedLabelValue) []string {
|
||||||
|
labelValues := make([]string, len(lvs)+len(curry))
|
||||||
|
var iCurry, iLVs int
|
||||||
|
for i := range labelValues {
|
||||||
|
if iCurry < len(curry) && curry[iCurry].index == i {
|
||||||
|
labelValues[i] = curry[iCurry].value
|
||||||
|
iCurry++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
labelValues[i] = lvs[iLVs]
|
||||||
|
iLVs++
|
||||||
|
}
|
||||||
|
return labelValues
|
||||||
|
}
|
||||||
|
|
|
@ -56,11 +56,11 @@ func (s *loggerSettings) apply(ctx *kingpin.ParseContext) error {
|
||||||
// To use the default Kingpin application, call AddFlags(kingpin.CommandLine)
|
// To use the default Kingpin application, call AddFlags(kingpin.CommandLine)
|
||||||
func AddFlags(a *kingpin.Application) {
|
func AddFlags(a *kingpin.Application) {
|
||||||
s := loggerSettings{}
|
s := loggerSettings{}
|
||||||
kingpin.Flag("log.level", "Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal]").
|
a.Flag("log.level", "Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal]").
|
||||||
Default(origLogger.Level.String()).
|
Default(origLogger.Level.String()).
|
||||||
StringVar(&s.level)
|
StringVar(&s.level)
|
||||||
defaultFormat := url.URL{Scheme: "logger", Opaque: "stderr"}
|
defaultFormat := url.URL{Scheme: "logger", Opaque: "stderr"}
|
||||||
kingpin.Flag("log.format", `Set the log target and format. Example: "logger:syslog?appname=bob&local=7" or "logger:stdout?json=true"`).
|
a.Flag("log.format", `Set the log target and format. Example: "logger:syslog?appname=bob&local=7" or "logger:stdout?json=true"`).
|
||||||
Default(defaultFormat.String()).
|
Default(defaultFormat.String()).
|
||||||
StringVar(&s.format)
|
StringVar(&s.format)
|
||||||
a.Action(s.apply)
|
a.Action(s.apply)
|
||||||
|
|
|
@ -214,6 +214,9 @@ func (d Duration) String() string {
|
||||||
ms = int64(time.Duration(d) / time.Millisecond)
|
ms = int64(time.Duration(d) / time.Millisecond)
|
||||||
unit = "ms"
|
unit = "ms"
|
||||||
)
|
)
|
||||||
|
if ms == 0 {
|
||||||
|
return "0s"
|
||||||
|
}
|
||||||
factors := map[string]int64{
|
factors := map[string]int64{
|
||||||
"y": 1000 * 60 * 60 * 24 * 365,
|
"y": 1000 * 60 * 60 * 24 * 365,
|
||||||
"w": 1000 * 60 * 60 * 24 * 7,
|
"w": 1000 * 60 * 60 * 24 * 7,
|
||||||
|
|
|
@ -93,7 +93,7 @@ func dehumanize(hbytes []byte) (uint64, error) {
|
||||||
'Z': ZiB,
|
'Z': ZiB,
|
||||||
'Y': YiB,
|
'Y': YiB,
|
||||||
}
|
}
|
||||||
mul = float64(multipliers[rune(lastByte)])
|
mul = multipliers[rune(lastByte)]
|
||||||
mant, err = parsePseudoFloat(string(hbytes))
|
mant, err = parsePseudoFloat(string(hbytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
@ -139,7 +139,7 @@ func (p *parser) readValue(fileName string) uint64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParsePriorityStats parses lines from the priority_stats file.
|
// ParsePriorityStats parses lines from the priority_stats file.
|
||||||
func parsePriorityStats(line string, ps *PriorityStats) (error) {
|
func parsePriorityStats(line string, ps *PriorityStats) error {
|
||||||
var (
|
var (
|
||||||
value uint64
|
value uint64
|
||||||
err error
|
err error
|
||||||
|
|
|
@ -62,7 +62,7 @@ func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) {
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
var err error
|
var err error
|
||||||
line := scanner.Text()
|
line := scanner.Text()
|
||||||
parts := strings.Fields(string(line))
|
parts := strings.Fields(line)
|
||||||
|
|
||||||
if len(parts) < 4 {
|
if len(parts) < 4 {
|
||||||
return nil, fmt.Errorf("invalid number of fields when parsing buddyinfo")
|
return nil, fmt.Errorf("invalid number of fields when parsing buddyinfo")
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
|
"github.com/prometheus/procfs/nfs"
|
||||||
"github.com/prometheus/procfs/xfs"
|
"github.com/prometheus/procfs/xfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -44,3 +45,25 @@ func (fs FS) XFSStats() (*xfs.Stats, error) {
|
||||||
|
|
||||||
return xfs.ParseStats(f)
|
return xfs.ParseStats(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NFSdClientRPCStats retrieves NFS daemon RPC statistics.
|
||||||
|
func (fs FS) NFSdClientRPCStats() (*nfs.ClientRPCStats, error) {
|
||||||
|
f, err := os.Open(fs.Path("net/rpc/nfs"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
return nfs.ParseClientRPCStats(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NFSdServerRPCStats retrieves NFS daemon RPC statistics.
|
||||||
|
func (fs FS) NFSdServerRPCStats() (*nfs.ServerRPCStats, error) {
|
||||||
|
f, err := os.Open(fs.Path("net/rpc/nfsd"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
return nfs.ParseServerRPCStats(f)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright 2018 The Prometheus Authors
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
// ParseUint32s parses a slice of strings into a slice of uint32s.
|
||||||
|
func ParseUint32s(ss []string) ([]uint32, error) {
|
||||||
|
us := make([]uint32, 0, len(ss))
|
||||||
|
for _, s := range ss {
|
||||||
|
u, err := strconv.ParseUint(s, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
us = append(us, uint32(u))
|
||||||
|
}
|
||||||
|
|
||||||
|
return us, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseUint64s parses a slice of strings into a slice of uint64s.
|
||||||
|
func ParseUint64s(ss []string) ([]uint64, error) {
|
||||||
|
us := make([]uint64, 0, len(ss))
|
||||||
|
for _, s := range ss {
|
||||||
|
u, err := strconv.ParseUint(s, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
us = append(us, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
return us, nil
|
||||||
|
}
|
|
@ -31,16 +31,16 @@ type IPVSStats struct {
|
||||||
type IPVSBackendStatus struct {
|
type IPVSBackendStatus struct {
|
||||||
// The local (virtual) IP address.
|
// The local (virtual) IP address.
|
||||||
LocalAddress net.IP
|
LocalAddress net.IP
|
||||||
|
// The remote (real) IP address.
|
||||||
|
RemoteAddress net.IP
|
||||||
// The local (virtual) port.
|
// The local (virtual) port.
|
||||||
LocalPort uint16
|
LocalPort uint16
|
||||||
|
// The remote (real) port.
|
||||||
|
RemotePort uint16
|
||||||
// The local firewall mark
|
// The local firewall mark
|
||||||
LocalMark string
|
LocalMark string
|
||||||
// The transport protocol (TCP, UDP).
|
// The transport protocol (TCP, UDP).
|
||||||
Proto string
|
Proto string
|
||||||
// The remote (real) IP address.
|
|
||||||
RemoteAddress net.IP
|
|
||||||
// The remote (real) port.
|
|
||||||
RemotePort uint16
|
|
||||||
// The current number of active connections for this virtual/real address pair.
|
// The current number of active connections for this virtual/real address pair.
|
||||||
ActiveConn uint64
|
ActiveConn uint64
|
||||||
// The current number of inactive connections for this virtual/real address pair.
|
// The current number of inactive connections for this virtual/real address pair.
|
||||||
|
@ -151,7 +151,7 @@ func parseIPVSBackendStatus(file io.Reader) ([]IPVSBackendStatus, error) {
|
||||||
)
|
)
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
fields := strings.Fields(string(scanner.Text()))
|
fields := strings.Fields(scanner.Text())
|
||||||
if len(fields) == 0 {
|
if len(fields) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,203 @@
|
||||||
|
package procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NetDevLine is single line parsed from /proc/net/dev or /proc/[pid]/net/dev.
|
||||||
|
type NetDevLine struct {
|
||||||
|
Name string `json:"name"` // The name of the interface.
|
||||||
|
RxBytes uint64 `json:"rx_bytes"` // Cumulative count of bytes received.
|
||||||
|
RxPackets uint64 `json:"rx_packets"` // Cumulative count of packets received.
|
||||||
|
RxErrors uint64 `json:"rx_errors"` // Cumulative count of receive errors encountered.
|
||||||
|
RxDropped uint64 `json:"rx_dropped"` // Cumulative count of packets dropped while receiving.
|
||||||
|
RxFIFO uint64 `json:"rx_fifo"` // Cumulative count of FIFO buffer errors.
|
||||||
|
RxFrame uint64 `json:"rx_frame"` // Cumulative count of packet framing errors.
|
||||||
|
RxCompressed uint64 `json:"rx_compressed"` // Cumulative count of compressed packets received by the device driver.
|
||||||
|
RxMulticast uint64 `json:"rx_multicast"` // Cumulative count of multicast frames received by the device driver.
|
||||||
|
TxBytes uint64 `json:"tx_bytes"` // Cumulative count of bytes transmitted.
|
||||||
|
TxPackets uint64 `json:"tx_packets"` // Cumulative count of packets transmitted.
|
||||||
|
TxErrors uint64 `json:"tx_errors"` // Cumulative count of transmit errors encountered.
|
||||||
|
TxDropped uint64 `json:"tx_dropped"` // Cumulative count of packets dropped while transmitting.
|
||||||
|
TxFIFO uint64 `json:"tx_fifo"` // Cumulative count of FIFO buffer errors.
|
||||||
|
TxCollisions uint64 `json:"tx_collisions"` // Cumulative count of collisions detected on the interface.
|
||||||
|
TxCarrier uint64 `json:"tx_carrier"` // Cumulative count of carrier losses detected by the device driver.
|
||||||
|
TxCompressed uint64 `json:"tx_compressed"` // Cumulative count of compressed packets transmitted by the device driver.
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetDev is parsed from /proc/net/dev or /proc/[pid]/net/dev. The map keys
|
||||||
|
// are interface names.
|
||||||
|
type NetDev map[string]NetDevLine
|
||||||
|
|
||||||
|
// NewNetDev returns kernel/system statistics read from /proc/net/dev.
|
||||||
|
func NewNetDev() (NetDev, error) {
|
||||||
|
fs, err := NewFS(DefaultMountPoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs.NewNetDev()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNetDev returns kernel/system statistics read from /proc/net/dev.
|
||||||
|
func (fs FS) NewNetDev() (NetDev, error) {
|
||||||
|
return newNetDev(fs.Path("net/dev"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNetDev returns kernel/system statistics read from /proc/[pid]/net/dev.
|
||||||
|
func (p Proc) NewNetDev() (NetDev, error) {
|
||||||
|
return newNetDev(p.path("net/dev"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// newNetDev creates a new NetDev from the contents of the given file.
|
||||||
|
func newNetDev(file string) (NetDev, error) {
|
||||||
|
f, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return NetDev{}, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
nd := NetDev{}
|
||||||
|
s := bufio.NewScanner(f)
|
||||||
|
for n := 0; s.Scan(); n++ {
|
||||||
|
// Skip the 2 header lines.
|
||||||
|
if n < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
line, err := nd.parseLine(s.Text())
|
||||||
|
if err != nil {
|
||||||
|
return nd, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nd[line.Name] = *line
|
||||||
|
}
|
||||||
|
|
||||||
|
return nd, s.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseLine parses a single line from the /proc/net/dev file. Header lines
|
||||||
|
// must be filtered prior to calling this method.
|
||||||
|
func (nd NetDev) parseLine(rawLine string) (*NetDevLine, error) {
|
||||||
|
parts := strings.SplitN(rawLine, ":", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return nil, errors.New("invalid net/dev line, missing colon")
|
||||||
|
}
|
||||||
|
fields := strings.Fields(strings.TrimSpace(parts[1]))
|
||||||
|
|
||||||
|
var err error
|
||||||
|
line := &NetDevLine{}
|
||||||
|
|
||||||
|
// Interface Name
|
||||||
|
line.Name = strings.TrimSpace(parts[0])
|
||||||
|
if line.Name == "" {
|
||||||
|
return nil, errors.New("invalid net/dev line, empty interface name")
|
||||||
|
}
|
||||||
|
|
||||||
|
// RX
|
||||||
|
line.RxBytes, err = strconv.ParseUint(fields[0], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line.RxPackets, err = strconv.ParseUint(fields[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line.RxErrors, err = strconv.ParseUint(fields[2], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line.RxDropped, err = strconv.ParseUint(fields[3], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line.RxFIFO, err = strconv.ParseUint(fields[4], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line.RxFrame, err = strconv.ParseUint(fields[5], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line.RxCompressed, err = strconv.ParseUint(fields[6], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line.RxMulticast, err = strconv.ParseUint(fields[7], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TX
|
||||||
|
line.TxBytes, err = strconv.ParseUint(fields[8], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line.TxPackets, err = strconv.ParseUint(fields[9], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line.TxErrors, err = strconv.ParseUint(fields[10], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line.TxDropped, err = strconv.ParseUint(fields[11], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line.TxFIFO, err = strconv.ParseUint(fields[12], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line.TxCollisions, err = strconv.ParseUint(fields[13], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line.TxCarrier, err = strconv.ParseUint(fields[14], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
line.TxCompressed, err = strconv.ParseUint(fields[15], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return line, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Total aggregates the values across interfaces and returns a new NetDevLine.
|
||||||
|
// The Name field will be a sorted comma seperated list of interface names.
|
||||||
|
func (nd NetDev) Total() NetDevLine {
|
||||||
|
total := NetDevLine{}
|
||||||
|
|
||||||
|
names := make([]string, 0, len(nd))
|
||||||
|
for _, ifc := range nd {
|
||||||
|
names = append(names, ifc.Name)
|
||||||
|
total.RxBytes += ifc.RxBytes
|
||||||
|
total.RxPackets += ifc.RxPackets
|
||||||
|
total.RxPackets += ifc.RxPackets
|
||||||
|
total.RxErrors += ifc.RxErrors
|
||||||
|
total.RxDropped += ifc.RxDropped
|
||||||
|
total.RxFIFO += ifc.RxFIFO
|
||||||
|
total.RxFrame += ifc.RxFrame
|
||||||
|
total.RxCompressed += ifc.RxCompressed
|
||||||
|
total.RxMulticast += ifc.RxMulticast
|
||||||
|
total.TxBytes += ifc.TxBytes
|
||||||
|
total.TxPackets += ifc.TxPackets
|
||||||
|
total.TxErrors += ifc.TxErrors
|
||||||
|
total.TxDropped += ifc.TxDropped
|
||||||
|
total.TxFIFO += ifc.TxFIFO
|
||||||
|
total.TxCollisions += ifc.TxCollisions
|
||||||
|
total.TxCarrier += ifc.TxCarrier
|
||||||
|
total.TxCompressed += ifc.TxCompressed
|
||||||
|
}
|
||||||
|
sort.Strings(names)
|
||||||
|
total.Name = strings.Join(names, ", ")
|
||||||
|
|
||||||
|
return total
|
||||||
|
}
|
|
@ -0,0 +1,263 @@
|
||||||
|
// Copyright 2018 The Prometheus Authors
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Package nfsd implements parsing of /proc/net/rpc/nfsd.
|
||||||
|
// Fields are documented in https://www.svennd.be/nfsd-stats-explained-procnetrpcnfsd/
|
||||||
|
package nfs
|
||||||
|
|
||||||
|
// ReplyCache models the "rc" line.
|
||||||
|
type ReplyCache struct {
|
||||||
|
Hits uint64
|
||||||
|
Misses uint64
|
||||||
|
NoCache uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileHandles models the "fh" line.
|
||||||
|
type FileHandles struct {
|
||||||
|
Stale uint64
|
||||||
|
TotalLookups uint64
|
||||||
|
AnonLookups uint64
|
||||||
|
DirNoCache uint64
|
||||||
|
NoDirNoCache uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// InputOutput models the "io" line.
|
||||||
|
type InputOutput struct {
|
||||||
|
Read uint64
|
||||||
|
Write uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Threads models the "th" line.
|
||||||
|
type Threads struct {
|
||||||
|
Threads uint64
|
||||||
|
FullCnt uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadAheadCache models the "ra" line.
|
||||||
|
type ReadAheadCache struct {
|
||||||
|
CacheSize uint64
|
||||||
|
CacheHistogram []uint64
|
||||||
|
NotFound uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Network models the "net" line.
|
||||||
|
type Network struct {
|
||||||
|
NetCount uint64
|
||||||
|
UDPCount uint64
|
||||||
|
TCPCount uint64
|
||||||
|
TCPConnect uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientRPC models the nfs "rpc" line.
|
||||||
|
type ClientRPC struct {
|
||||||
|
RPCCount uint64
|
||||||
|
Retransmissions uint64
|
||||||
|
AuthRefreshes uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServerRPC models the nfsd "rpc" line.
|
||||||
|
type ServerRPC struct {
|
||||||
|
RPCCount uint64
|
||||||
|
BadCnt uint64
|
||||||
|
BadFmt uint64
|
||||||
|
BadAuth uint64
|
||||||
|
BadcInt uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// V2Stats models the "proc2" line.
|
||||||
|
type V2Stats struct {
|
||||||
|
Null uint64
|
||||||
|
GetAttr uint64
|
||||||
|
SetAttr uint64
|
||||||
|
Root uint64
|
||||||
|
Lookup uint64
|
||||||
|
ReadLink uint64
|
||||||
|
Read uint64
|
||||||
|
WrCache uint64
|
||||||
|
Write uint64
|
||||||
|
Create uint64
|
||||||
|
Remove uint64
|
||||||
|
Rename uint64
|
||||||
|
Link uint64
|
||||||
|
SymLink uint64
|
||||||
|
MkDir uint64
|
||||||
|
RmDir uint64
|
||||||
|
ReadDir uint64
|
||||||
|
FsStat uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// V3Stats models the "proc3" line.
|
||||||
|
type V3Stats struct {
|
||||||
|
Null uint64
|
||||||
|
GetAttr uint64
|
||||||
|
SetAttr uint64
|
||||||
|
Lookup uint64
|
||||||
|
Access uint64
|
||||||
|
ReadLink uint64
|
||||||
|
Read uint64
|
||||||
|
Write uint64
|
||||||
|
Create uint64
|
||||||
|
MkDir uint64
|
||||||
|
SymLink uint64
|
||||||
|
MkNod uint64
|
||||||
|
Remove uint64
|
||||||
|
RmDir uint64
|
||||||
|
Rename uint64
|
||||||
|
Link uint64
|
||||||
|
ReadDir uint64
|
||||||
|
ReadDirPlus uint64
|
||||||
|
FsStat uint64
|
||||||
|
FsInfo uint64
|
||||||
|
PathConf uint64
|
||||||
|
Commit uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientV4Stats models the nfs "proc4" line.
|
||||||
|
type ClientV4Stats struct {
|
||||||
|
Null uint64
|
||||||
|
Read uint64
|
||||||
|
Write uint64
|
||||||
|
Commit uint64
|
||||||
|
Open uint64
|
||||||
|
OpenConfirm uint64
|
||||||
|
OpenNoattr uint64
|
||||||
|
OpenDowngrade uint64
|
||||||
|
Close uint64
|
||||||
|
Setattr uint64
|
||||||
|
FsInfo uint64
|
||||||
|
Renew uint64
|
||||||
|
SetClientId uint64
|
||||||
|
SetClientIdConfirm uint64
|
||||||
|
Lock uint64
|
||||||
|
Lockt uint64
|
||||||
|
Locku uint64
|
||||||
|
Access uint64
|
||||||
|
Getattr uint64
|
||||||
|
Lookup uint64
|
||||||
|
LookupRoot uint64
|
||||||
|
Remove uint64
|
||||||
|
Rename uint64
|
||||||
|
Link uint64
|
||||||
|
Symlink uint64
|
||||||
|
Create uint64
|
||||||
|
Pathconf uint64
|
||||||
|
StatFs uint64
|
||||||
|
ReadLink uint64
|
||||||
|
ReadDir uint64
|
||||||
|
ServerCaps uint64
|
||||||
|
DelegReturn uint64
|
||||||
|
GetAcl uint64
|
||||||
|
SetAcl uint64
|
||||||
|
FsLocations uint64
|
||||||
|
ReleaseLockowner uint64
|
||||||
|
Secinfo uint64
|
||||||
|
FsidPresent uint64
|
||||||
|
ExchangeId uint64
|
||||||
|
CreateSession uint64
|
||||||
|
DestroySession uint64
|
||||||
|
Sequence uint64
|
||||||
|
GetLeaseTime uint64
|
||||||
|
ReclaimComplete uint64
|
||||||
|
LayoutGet uint64
|
||||||
|
GetDeviceInfo uint64
|
||||||
|
LayoutCommit uint64
|
||||||
|
LayoutReturn uint64
|
||||||
|
SecinfoNoName uint64
|
||||||
|
TestStateId uint64
|
||||||
|
FreeStateId uint64
|
||||||
|
GetDeviceList uint64
|
||||||
|
BindConnToSession uint64
|
||||||
|
DestroyClientId uint64
|
||||||
|
Seek uint64
|
||||||
|
Allocate uint64
|
||||||
|
DeAllocate uint64
|
||||||
|
LayoutStats uint64
|
||||||
|
Clone uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServerV4Stats models the nfsd "proc4" line.
|
||||||
|
type ServerV4Stats struct {
|
||||||
|
Null uint64
|
||||||
|
Compound uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// V4Ops models the "proc4ops" line: NFSv4 operations
|
||||||
|
// Variable list, see:
|
||||||
|
// v4.0 https://tools.ietf.org/html/rfc3010 (38 operations)
|
||||||
|
// v4.1 https://tools.ietf.org/html/rfc5661 (58 operations)
|
||||||
|
// v4.2 https://tools.ietf.org/html/draft-ietf-nfsv4-minorversion2-41 (71 operations)
|
||||||
|
type V4Ops struct {
|
||||||
|
//Values uint64 // Variable depending on v4.x sub-version. TODO: Will this always at least include the fields in this struct?
|
||||||
|
Op0Unused uint64
|
||||||
|
Op1Unused uint64
|
||||||
|
Op2Future uint64
|
||||||
|
Access uint64
|
||||||
|
Close uint64
|
||||||
|
Commit uint64
|
||||||
|
Create uint64
|
||||||
|
DelegPurge uint64
|
||||||
|
DelegReturn uint64
|
||||||
|
GetAttr uint64
|
||||||
|
GetFH uint64
|
||||||
|
Link uint64
|
||||||
|
Lock uint64
|
||||||
|
Lockt uint64
|
||||||
|
Locku uint64
|
||||||
|
Lookup uint64
|
||||||
|
LookupRoot uint64
|
||||||
|
Nverify uint64
|
||||||
|
Open uint64
|
||||||
|
OpenAttr uint64
|
||||||
|
OpenConfirm uint64
|
||||||
|
OpenDgrd uint64
|
||||||
|
PutFH uint64
|
||||||
|
PutPubFH uint64
|
||||||
|
PutRootFH uint64
|
||||||
|
Read uint64
|
||||||
|
ReadDir uint64
|
||||||
|
ReadLink uint64
|
||||||
|
Remove uint64
|
||||||
|
Rename uint64
|
||||||
|
Renew uint64
|
||||||
|
RestoreFH uint64
|
||||||
|
SaveFH uint64
|
||||||
|
SecInfo uint64
|
||||||
|
SetAttr uint64
|
||||||
|
Verify uint64
|
||||||
|
Write uint64
|
||||||
|
RelLockOwner uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// RPCStats models all stats from /proc/net/rpc/nfs.
|
||||||
|
type ClientRPCStats struct {
|
||||||
|
Network Network
|
||||||
|
ClientRPC ClientRPC
|
||||||
|
V2Stats V2Stats
|
||||||
|
V3Stats V3Stats
|
||||||
|
ClientV4Stats ClientV4Stats
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServerRPCStats models all stats from /proc/net/rpc/nfsd.
|
||||||
|
type ServerRPCStats struct {
|
||||||
|
ReplyCache ReplyCache
|
||||||
|
FileHandles FileHandles
|
||||||
|
InputOutput InputOutput
|
||||||
|
Threads Threads
|
||||||
|
ReadAheadCache ReadAheadCache
|
||||||
|
Network Network
|
||||||
|
ServerRPC ServerRPC
|
||||||
|
V2Stats V2Stats
|
||||||
|
V3Stats V3Stats
|
||||||
|
ServerV4Stats ServerV4Stats
|
||||||
|
V4Ops V4Ops
|
||||||
|
}
|
|
@ -0,0 +1,308 @@
|
||||||
|
// Copyright 2018 The Prometheus Authors
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package nfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseReplyCache(v []uint64) (ReplyCache, error) {
|
||||||
|
if len(v) != 3 {
|
||||||
|
return ReplyCache{}, fmt.Errorf("invalid ReplyCache line %q", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReplyCache{
|
||||||
|
Hits: v[0],
|
||||||
|
Misses: v[1],
|
||||||
|
NoCache: v[2],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFileHandles(v []uint64) (FileHandles, error) {
|
||||||
|
if len(v) != 5 {
|
||||||
|
return FileHandles{}, fmt.Errorf("invalid FileHandles, line %q", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return FileHandles{
|
||||||
|
Stale: v[0],
|
||||||
|
TotalLookups: v[1],
|
||||||
|
AnonLookups: v[2],
|
||||||
|
DirNoCache: v[3],
|
||||||
|
NoDirNoCache: v[4],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInputOutput(v []uint64) (InputOutput, error) {
|
||||||
|
if len(v) != 2 {
|
||||||
|
return InputOutput{}, fmt.Errorf("invalid InputOutput line %q", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return InputOutput{
|
||||||
|
Read: v[0],
|
||||||
|
Write: v[1],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseThreads(v []uint64) (Threads, error) {
|
||||||
|
if len(v) != 2 {
|
||||||
|
return Threads{}, fmt.Errorf("invalid Threads line %q", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Threads{
|
||||||
|
Threads: v[0],
|
||||||
|
FullCnt: v[1],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseReadAheadCache(v []uint64) (ReadAheadCache, error) {
|
||||||
|
if len(v) != 12 {
|
||||||
|
return ReadAheadCache{}, fmt.Errorf("invalid ReadAheadCache line %q", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReadAheadCache{
|
||||||
|
CacheSize: v[0],
|
||||||
|
CacheHistogram: v[1:11],
|
||||||
|
NotFound: v[11],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseNetwork(v []uint64) (Network, error) {
|
||||||
|
if len(v) != 4 {
|
||||||
|
return Network{}, fmt.Errorf("invalid Network line %q", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Network{
|
||||||
|
NetCount: v[0],
|
||||||
|
UDPCount: v[1],
|
||||||
|
TCPCount: v[2],
|
||||||
|
TCPConnect: v[3],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseServerRPC(v []uint64) (ServerRPC, error) {
|
||||||
|
if len(v) != 5 {
|
||||||
|
return ServerRPC{}, fmt.Errorf("invalid RPC line %q", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ServerRPC{
|
||||||
|
RPCCount: v[0],
|
||||||
|
BadCnt: v[1],
|
||||||
|
BadFmt: v[2],
|
||||||
|
BadAuth: v[3],
|
||||||
|
BadcInt: v[4],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseClientRPC(v []uint64) (ClientRPC, error) {
|
||||||
|
if len(v) != 3 {
|
||||||
|
return ClientRPC{}, fmt.Errorf("invalid RPC line %q", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ClientRPC{
|
||||||
|
RPCCount: v[0],
|
||||||
|
Retransmissions: v[1],
|
||||||
|
AuthRefreshes: v[2],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseV2Stats(v []uint64) (V2Stats, error) {
|
||||||
|
values := int(v[0])
|
||||||
|
if len(v[1:]) != values || values != 18 {
|
||||||
|
return V2Stats{}, fmt.Errorf("invalid V2Stats line %q", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return V2Stats{
|
||||||
|
Null: v[1],
|
||||||
|
GetAttr: v[2],
|
||||||
|
SetAttr: v[3],
|
||||||
|
Root: v[4],
|
||||||
|
Lookup: v[5],
|
||||||
|
ReadLink: v[6],
|
||||||
|
Read: v[7],
|
||||||
|
WrCache: v[8],
|
||||||
|
Write: v[9],
|
||||||
|
Create: v[10],
|
||||||
|
Remove: v[11],
|
||||||
|
Rename: v[12],
|
||||||
|
Link: v[13],
|
||||||
|
SymLink: v[14],
|
||||||
|
MkDir: v[15],
|
||||||
|
RmDir: v[16],
|
||||||
|
ReadDir: v[17],
|
||||||
|
FsStat: v[18],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseV3Stats(v []uint64) (V3Stats, error) {
|
||||||
|
values := int(v[0])
|
||||||
|
if len(v[1:]) != values || values != 22 {
|
||||||
|
return V3Stats{}, fmt.Errorf("invalid V3Stats line %q", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return V3Stats{
|
||||||
|
Null: v[1],
|
||||||
|
GetAttr: v[2],
|
||||||
|
SetAttr: v[3],
|
||||||
|
Lookup: v[4],
|
||||||
|
Access: v[5],
|
||||||
|
ReadLink: v[6],
|
||||||
|
Read: v[7],
|
||||||
|
Write: v[8],
|
||||||
|
Create: v[9],
|
||||||
|
MkDir: v[10],
|
||||||
|
SymLink: v[11],
|
||||||
|
MkNod: v[12],
|
||||||
|
Remove: v[13],
|
||||||
|
RmDir: v[14],
|
||||||
|
Rename: v[15],
|
||||||
|
Link: v[16],
|
||||||
|
ReadDir: v[17],
|
||||||
|
ReadDirPlus: v[18],
|
||||||
|
FsStat: v[19],
|
||||||
|
FsInfo: v[20],
|
||||||
|
PathConf: v[21],
|
||||||
|
Commit: v[22],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseClientV4Stats(v []uint64) (ClientV4Stats, error) {
|
||||||
|
values := int(v[0])
|
||||||
|
if len(v[1:]) != values || values < 59 {
|
||||||
|
return ClientV4Stats{}, fmt.Errorf("invalid V4Stats line %q", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ClientV4Stats{
|
||||||
|
Null: v[1],
|
||||||
|
Read: v[2],
|
||||||
|
Write: v[3],
|
||||||
|
Commit: v[4],
|
||||||
|
Open: v[5],
|
||||||
|
OpenConfirm: v[6],
|
||||||
|
OpenNoattr: v[7],
|
||||||
|
OpenDowngrade: v[8],
|
||||||
|
Close: v[9],
|
||||||
|
Setattr: v[10],
|
||||||
|
FsInfo: v[11],
|
||||||
|
Renew: v[12],
|
||||||
|
SetClientId: v[13],
|
||||||
|
SetClientIdConfirm: v[14],
|
||||||
|
Lock: v[15],
|
||||||
|
Lockt: v[16],
|
||||||
|
Locku: v[17],
|
||||||
|
Access: v[18],
|
||||||
|
Getattr: v[19],
|
||||||
|
Lookup: v[20],
|
||||||
|
LookupRoot: v[21],
|
||||||
|
Remove: v[22],
|
||||||
|
Rename: v[23],
|
||||||
|
Link: v[24],
|
||||||
|
Symlink: v[25],
|
||||||
|
Create: v[26],
|
||||||
|
Pathconf: v[27],
|
||||||
|
StatFs: v[28],
|
||||||
|
ReadLink: v[29],
|
||||||
|
ReadDir: v[30],
|
||||||
|
ServerCaps: v[31],
|
||||||
|
DelegReturn: v[32],
|
||||||
|
GetAcl: v[33],
|
||||||
|
SetAcl: v[34],
|
||||||
|
FsLocations: v[35],
|
||||||
|
ReleaseLockowner: v[36],
|
||||||
|
Secinfo: v[37],
|
||||||
|
FsidPresent: v[38],
|
||||||
|
ExchangeId: v[39],
|
||||||
|
CreateSession: v[40],
|
||||||
|
DestroySession: v[41],
|
||||||
|
Sequence: v[42],
|
||||||
|
GetLeaseTime: v[43],
|
||||||
|
ReclaimComplete: v[44],
|
||||||
|
LayoutGet: v[45],
|
||||||
|
GetDeviceInfo: v[46],
|
||||||
|
LayoutCommit: v[47],
|
||||||
|
LayoutReturn: v[48],
|
||||||
|
SecinfoNoName: v[49],
|
||||||
|
TestStateId: v[50],
|
||||||
|
FreeStateId: v[51],
|
||||||
|
GetDeviceList: v[52],
|
||||||
|
BindConnToSession: v[53],
|
||||||
|
DestroyClientId: v[54],
|
||||||
|
Seek: v[55],
|
||||||
|
Allocate: v[56],
|
||||||
|
DeAllocate: v[57],
|
||||||
|
LayoutStats: v[58],
|
||||||
|
Clone: v[59],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseServerV4Stats(v []uint64) (ServerV4Stats, error) {
|
||||||
|
values := int(v[0])
|
||||||
|
if len(v[1:]) != values || values != 2 {
|
||||||
|
return ServerV4Stats{}, fmt.Errorf("invalid V4Stats line %q", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ServerV4Stats{
|
||||||
|
Null: v[1],
|
||||||
|
Compound: v[2],
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseV4Ops(v []uint64) (V4Ops, error) {
|
||||||
|
values := int(v[0])
|
||||||
|
if len(v[1:]) != values || values < 39 {
|
||||||
|
return V4Ops{}, fmt.Errorf("invalid V4Ops line %q", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
stats := V4Ops{
|
||||||
|
Op0Unused: v[1],
|
||||||
|
Op1Unused: v[2],
|
||||||
|
Op2Future: v[3],
|
||||||
|
Access: v[4],
|
||||||
|
Close: v[5],
|
||||||
|
Commit: v[6],
|
||||||
|
Create: v[7],
|
||||||
|
DelegPurge: v[8],
|
||||||
|
DelegReturn: v[9],
|
||||||
|
GetAttr: v[10],
|
||||||
|
GetFH: v[11],
|
||||||
|
Link: v[12],
|
||||||
|
Lock: v[13],
|
||||||
|
Lockt: v[14],
|
||||||
|
Locku: v[15],
|
||||||
|
Lookup: v[16],
|
||||||
|
LookupRoot: v[17],
|
||||||
|
Nverify: v[18],
|
||||||
|
Open: v[19],
|
||||||
|
OpenAttr: v[20],
|
||||||
|
OpenConfirm: v[21],
|
||||||
|
OpenDgrd: v[22],
|
||||||
|
PutFH: v[23],
|
||||||
|
PutPubFH: v[24],
|
||||||
|
PutRootFH: v[25],
|
||||||
|
Read: v[26],
|
||||||
|
ReadDir: v[27],
|
||||||
|
ReadLink: v[28],
|
||||||
|
Remove: v[29],
|
||||||
|
Rename: v[30],
|
||||||
|
Renew: v[31],
|
||||||
|
RestoreFH: v[32],
|
||||||
|
SaveFH: v[33],
|
||||||
|
SecInfo: v[34],
|
||||||
|
SetAttr: v[35],
|
||||||
|
Verify: v[36],
|
||||||
|
Write: v[37],
|
||||||
|
RelLockOwner: v[38],
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats, nil
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
// Copyright 2018 The Prometheus Authors
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package nfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/prometheus/procfs/internal/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParseClientRPCStats returns stats read from /proc/net/rpc/nfs
|
||||||
|
func ParseClientRPCStats(r io.Reader) (*ClientRPCStats, error) {
|
||||||
|
stats := &ClientRPCStats{}
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(r)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
parts := strings.Fields(scanner.Text())
|
||||||
|
// require at least <key> <value>
|
||||||
|
if len(parts) < 2 {
|
||||||
|
return nil, fmt.Errorf("invalid NFSd metric line %q", line)
|
||||||
|
}
|
||||||
|
|
||||||
|
values, err := util.ParseUint64s(parts[1:])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error parsing NFSd metric line: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch metricLine := parts[0]; metricLine {
|
||||||
|
case "net":
|
||||||
|
stats.Network, err = parseNetwork(values)
|
||||||
|
case "rpc":
|
||||||
|
stats.ClientRPC, err = parseClientRPC(values)
|
||||||
|
case "proc2":
|
||||||
|
stats.V2Stats, err = parseV2Stats(values)
|
||||||
|
case "proc3":
|
||||||
|
stats.V3Stats, err = parseV3Stats(values)
|
||||||
|
case "proc4":
|
||||||
|
stats.ClientV4Stats, err = parseClientV4Stats(values)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown NFSd metric line %q", metricLine)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("errors parsing NFSd metric line: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return nil, fmt.Errorf("error scanning NFSd file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats, nil
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
// Copyright 2018 The Prometheus Authors
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package nfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/prometheus/procfs/internal/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParseServerRPCStats returns stats read from /proc/net/rpc/nfsd
|
||||||
|
func ParseServerRPCStats(r io.Reader) (*ServerRPCStats, error) {
|
||||||
|
stats := &ServerRPCStats{}
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(r)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
parts := strings.Fields(scanner.Text())
|
||||||
|
// require at least <key> <value>
|
||||||
|
if len(parts) < 2 {
|
||||||
|
return nil, fmt.Errorf("invalid NFSd metric line %q", line)
|
||||||
|
}
|
||||||
|
label := parts[0]
|
||||||
|
|
||||||
|
var values []uint64
|
||||||
|
var err error
|
||||||
|
if label == "th" {
|
||||||
|
if len(parts) < 3 {
|
||||||
|
return nil, fmt.Errorf("invalid NFSd th metric line %q", line)
|
||||||
|
}
|
||||||
|
values, err = util.ParseUint64s(parts[1:3])
|
||||||
|
} else {
|
||||||
|
values, err = util.ParseUint64s(parts[1:])
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error parsing NFSd metric line: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch metricLine := parts[0]; metricLine {
|
||||||
|
case "rc":
|
||||||
|
stats.ReplyCache, err = parseReplyCache(values)
|
||||||
|
case "fh":
|
||||||
|
stats.FileHandles, err = parseFileHandles(values)
|
||||||
|
case "io":
|
||||||
|
stats.InputOutput, err = parseInputOutput(values)
|
||||||
|
case "th":
|
||||||
|
stats.Threads, err = parseThreads(values)
|
||||||
|
case "ra":
|
||||||
|
stats.ReadAheadCache, err = parseReadAheadCache(values)
|
||||||
|
case "net":
|
||||||
|
stats.Network, err = parseNetwork(values)
|
||||||
|
case "rpc":
|
||||||
|
stats.ServerRPC, err = parseServerRPC(values)
|
||||||
|
case "proc2":
|
||||||
|
stats.V2Stats, err = parseV2Stats(values)
|
||||||
|
case "proc3":
|
||||||
|
stats.V3Stats, err = parseV3Stats(values)
|
||||||
|
case "proc4":
|
||||||
|
stats.ServerV4Stats, err = parseServerV4Stats(values)
|
||||||
|
case "proc4ops":
|
||||||
|
stats.V4Ops, err = parseV4Ops(values)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown NFSd metric line %q", metricLine)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("errors parsing NFSd metric line: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return nil, fmt.Errorf("error scanning NFSd file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats, nil
|
||||||
|
}
|
|
@ -47,9 +47,6 @@ func (p Proc) NewIO() (ProcIO, error) {
|
||||||
|
|
||||||
_, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR,
|
_, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR,
|
||||||
&pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes)
|
&pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes)
|
||||||
if err != nil {
|
|
||||||
return pio, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return pio, nil
|
return pio, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Namespace represents a single namespace of a process.
|
||||||
|
type Namespace struct {
|
||||||
|
Type string // Namespace type.
|
||||||
|
Inode uint32 // Inode number of the namespace. If two processes are in the same namespace their inodes will match.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Namespaces contains all of the namespaces that the process is contained in.
|
||||||
|
type Namespaces map[string]Namespace
|
||||||
|
|
||||||
|
// NewNamespaces reads from /proc/[pid/ns/* to get the namespaces of which the
|
||||||
|
// process is a member.
|
||||||
|
func (p Proc) NewNamespaces() (Namespaces, error) {
|
||||||
|
d, err := os.Open(p.path("ns"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer d.Close()
|
||||||
|
|
||||||
|
names, err := d.Readdirnames(-1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read contents of ns dir: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ns := make(Namespaces, len(names))
|
||||||
|
for _, name := range names {
|
||||||
|
target, err := os.Readlink(p.path("ns", name))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fields := strings.SplitN(target, ":", 2)
|
||||||
|
if len(fields) != 2 {
|
||||||
|
return nil, fmt.Errorf("failed to parse namespace type and inode from '%v'", target)
|
||||||
|
}
|
||||||
|
|
||||||
|
typ := fields[0]
|
||||||
|
inode, err := strconv.ParseUint(strings.Trim(fields[1], "[]"), 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse inode from '%v': %v", fields[1], err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ns[name] = Namespace{typ, uint32(inode)}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ns, nil
|
||||||
|
}
|
|
@ -17,8 +17,9 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/prometheus/procfs/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseStats parses a Stats from an input io.Reader, using the format
|
// ParseStats parses a Stats from an input io.Reader, using the format
|
||||||
|
@ -68,7 +69,7 @@ func ParseStats(r io.Reader) (*Stats, error) {
|
||||||
|
|
||||||
// Extended precision counters are uint64 values.
|
// Extended precision counters are uint64 values.
|
||||||
if label == fieldXpc {
|
if label == fieldXpc {
|
||||||
us, err := parseUint64s(ss[1:])
|
us, err := util.ParseUint64s(ss[1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -82,7 +83,7 @@ func ParseStats(r io.Reader) (*Stats, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// All other counters are uint32 values.
|
// All other counters are uint32 values.
|
||||||
us, err := parseUint32s(ss[1:])
|
us, err := util.ParseUint32s(ss[1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -327,33 +328,3 @@ func extendedPrecisionStats(us []uint64) (ExtendedPrecisionStats, error) {
|
||||||
ReadBytes: us[2],
|
ReadBytes: us[2],
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseUint32s parses a slice of strings into a slice of uint32s.
|
|
||||||
func parseUint32s(ss []string) ([]uint32, error) {
|
|
||||||
us := make([]uint32, 0, len(ss))
|
|
||||||
for _, s := range ss {
|
|
||||||
u, err := strconv.ParseUint(s, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
us = append(us, uint32(u))
|
|
||||||
}
|
|
||||||
|
|
||||||
return us, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseUint64s parses a slice of strings into a slice of uint64s.
|
|
||||||
func parseUint64s(ss []string) ([]uint64, error) {
|
|
||||||
us := make([]uint64, 0, len(ss))
|
|
||||||
for _, s := range ss {
|
|
||||||
u, err := strconv.ParseUint(s, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
us = append(us, u)
|
|
||||||
}
|
|
||||||
|
|
||||||
return us, nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
# 1.0.4
|
||||||
|
|
||||||
|
* Fix race when adding hooks (#612)
|
||||||
|
* Fix terminal check in AppEngine (#635)
|
||||||
|
|
||||||
# 1.0.3
|
# 1.0.3
|
||||||
|
|
||||||
* Replace example files with testable examples
|
* Replace example files with testable examples
|
||||||
|
|
|
@ -247,6 +247,7 @@ Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/v
|
||||||
| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. |
|
| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. |
|
||||||
| [Amazon Kinesis](https://github.com/evalphobia/logrus_kinesis) | Hook for logging to [Amazon Kinesis](https://aws.amazon.com/kinesis/) |
|
| [Amazon Kinesis](https://github.com/evalphobia/logrus_kinesis) | Hook for logging to [Amazon Kinesis](https://aws.amazon.com/kinesis/) |
|
||||||
| [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) |
|
| [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) |
|
||||||
|
| [AzureTableHook](https://github.com/kpfaulkner/azuretablehook/) | Hook for logging to Azure Table Storage|
|
||||||
| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. |
|
| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. |
|
||||||
| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic |
|
| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic |
|
||||||
| [Discordrus](https://github.com/kz/discordrus) | Hook for logging to [Discord](https://discordapp.com/) |
|
| [Discordrus](https://github.com/kz/discordrus) | Hook for logging to [Discord](https://discordapp.com/) |
|
||||||
|
@ -260,8 +261,9 @@ Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/v
|
||||||
| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb |
|
| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb |
|
||||||
| [Influxus](http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB](http://influxdata.com/) |
|
| [Influxus](http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB](http://influxdata.com/) |
|
||||||
| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` |
|
| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` |
|
||||||
| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka |
|
| [KafkaLogrus](https://github.com/tracer0tong/kafkalogrus) | Hook for logging to Kafka |
|
||||||
| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem |
|
| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem |
|
||||||
|
| [Logbeat](https://github.com/macandmia/logbeat) | Hook for logging to [Opbeat](https://opbeat.com/) |
|
||||||
| [Logentries](https://github.com/jcftang/logentriesrus) | Hook for logging to [Logentries](https://logentries.com/) |
|
| [Logentries](https://github.com/jcftang/logentriesrus) | Hook for logging to [Logentries](https://logentries.com/) |
|
||||||
| [Logentrus](https://github.com/puddingfactory/logentrus) | Hook for logging to [Logentries](https://logentries.com/) |
|
| [Logentrus](https://github.com/puddingfactory/logentrus) | Hook for logging to [Logentries](https://logentries.com/) |
|
||||||
| [Logmatic.io](https://github.com/logmatic/logmatic-go) | Hook for logging to [Logmatic.io](http://logmatic.io/) |
|
| [Logmatic.io](https://github.com/logmatic/logmatic-go) | Hook for logging to [Logmatic.io](http://logmatic.io/) |
|
||||||
|
@ -274,6 +276,7 @@ Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/v
|
||||||
| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit |
|
| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit |
|
||||||
| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. |
|
| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. |
|
||||||
| [PostgreSQL](https://github.com/gemnasium/logrus-postgresql-hook) | Send logs to [PostgreSQL](http://postgresql.org) |
|
| [PostgreSQL](https://github.com/gemnasium/logrus-postgresql-hook) | Send logs to [PostgreSQL](http://postgresql.org) |
|
||||||
|
| [Promrus](https://github.com/weaveworks/promrus) | Expose number of log messages as [Prometheus](https://prometheus.io/) metrics |
|
||||||
| [Pushover](https://github.com/toorop/logrus_pushover) | Send error via [Pushover](https://pushover.net) |
|
| [Pushover](https://github.com/toorop/logrus_pushover) | Send error via [Pushover](https://pushover.net) |
|
||||||
| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) |
|
| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) |
|
||||||
| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) |
|
| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) |
|
||||||
|
@ -285,6 +288,7 @@ Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/v
|
||||||
| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)|
|
| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)|
|
||||||
| [Syslog](https://github.com/sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. |
|
| [Syslog](https://github.com/sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. |
|
||||||
| [Syslog TLS](https://github.com/shinji62/logrus-syslog-ng) | Send errors to remote syslog server with TLS support. |
|
| [Syslog TLS](https://github.com/shinji62/logrus-syslog-ng) | Send errors to remote syslog server with TLS support. |
|
||||||
|
| [Telegram](https://github.com/rossmcdonald/telegram_hook) | Hook for logging errors to [Telegram](https://telegram.org/) |
|
||||||
| [TraceView](https://github.com/evalphobia/logrus_appneta) | Hook for logging to [AppNeta TraceView](https://www.appneta.com/products/traceview/) |
|
| [TraceView](https://github.com/evalphobia/logrus_appneta) | Hook for logging to [AppNeta TraceView](https://www.appneta.com/products/traceview/) |
|
||||||
| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) |
|
| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) |
|
||||||
| [logz.io](https://github.com/ripcurld00d/logrus-logzio-hook) | Hook for logging to [logz.io](https://logz.io), a Log as a Service using Logstash |
|
| [logz.io](https://github.com/ripcurld00d/logrus-logzio-hook) | Hook for logging to [logz.io](https://logz.io), a Log as a Service using Logstash |
|
||||||
|
@ -372,7 +376,7 @@ The built-in logging formatters are:
|
||||||
|
|
||||||
Third party logging formatters:
|
Third party logging formatters:
|
||||||
|
|
||||||
* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can by parsed by Kubernetes and Google Container Engine.
|
* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can be parsed by Kubernetes and Google Container Engine.
|
||||||
* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
|
* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
|
||||||
* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
|
* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
|
||||||
* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
|
* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
|
||||||
|
|
|
@ -94,7 +94,10 @@ func (entry Entry) log(level Level, msg string) {
|
||||||
entry.Level = level
|
entry.Level = level
|
||||||
entry.Message = msg
|
entry.Message = msg
|
||||||
|
|
||||||
if err := entry.Logger.Hooks.Fire(level, &entry); err != nil {
|
entry.Logger.mu.Lock()
|
||||||
|
err := entry.Logger.Hooks.Fire(level, &entry)
|
||||||
|
entry.Logger.mu.Unlock()
|
||||||
|
if err != nil {
|
||||||
entry.Logger.mu.Lock()
|
entry.Logger.mu.Lock()
|
||||||
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
|
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
|
||||||
entry.Logger.mu.Unlock()
|
entry.Logger.mu.Unlock()
|
||||||
|
|
|
@ -315,3 +315,9 @@ func (logger *Logger) level() Level {
|
||||||
func (logger *Logger) SetLevel(level Level) {
|
func (logger *Logger) SetLevel(level Level) {
|
||||||
atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
|
atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (logger *Logger) AddHook(hook Hook) {
|
||||||
|
logger.mu.Lock()
|
||||||
|
defer logger.mu.Unlock()
|
||||||
|
logger.Hooks.Add(hook)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
// +build appengine
|
||||||
|
|
||||||
|
package logrus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func checkIfTerminal(w io.Writer) bool {
|
||||||
|
return true
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
// +build !appengine
|
||||||
|
|
||||||
|
package logrus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
|
)
|
||||||
|
|
||||||
|
func checkIfTerminal(w io.Writer) bool {
|
||||||
|
switch v := w.(type) {
|
||||||
|
case *os.File:
|
||||||
|
return terminal.IsTerminal(int(v.Fd()))
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,14 +3,10 @@ package logrus
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -65,16 +61,7 @@ type TextFormatter struct {
|
||||||
|
|
||||||
func (f *TextFormatter) init(entry *Entry) {
|
func (f *TextFormatter) init(entry *Entry) {
|
||||||
if entry.Logger != nil {
|
if entry.Logger != nil {
|
||||||
f.isTerminal = f.checkIfTerminal(entry.Logger.Out)
|
f.isTerminal = checkIfTerminal(entry.Logger.Out)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *TextFormatter) checkIfTerminal(w io.Writer) bool {
|
|
||||||
switch v := w.(type) {
|
|
||||||
case *os.File:
|
|
||||||
return terminal.IsTerminal(int(v.Fd()))
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -617,7 +617,7 @@ func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) {
|
||||||
if _, err = w.Write(crlf); err != nil {
|
if _, err = w.Write(crlf); err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
n += 1
|
n++
|
||||||
buf = buf[1:]
|
buf = buf[1:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,44 +17,41 @@
|
||||||
package terminal // import "golang.org/x/crypto/ssh/terminal"
|
package terminal // import "golang.org/x/crypto/ssh/terminal"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// State contains the state of a terminal.
|
// State contains the state of a terminal.
|
||||||
type State struct {
|
type State struct {
|
||||||
termios syscall.Termios
|
termios unix.Termios
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||||
func IsTerminal(fd int) bool {
|
func IsTerminal(fd int) bool {
|
||||||
var termios syscall.Termios
|
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
return err == nil
|
||||||
return err == 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeRaw put the terminal connected to the given file descriptor into raw
|
// MakeRaw put the terminal connected to the given file descriptor into raw
|
||||||
// mode and returns the previous state of the terminal so that it can be
|
// mode and returns the previous state of the terminal so that it can be
|
||||||
// restored.
|
// restored.
|
||||||
func MakeRaw(fd int) (*State, error) {
|
func MakeRaw(fd int) (*State, error) {
|
||||||
var oldState State
|
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
newState := oldState.termios
|
oldState := State{termios: *termios}
|
||||||
|
|
||||||
// This attempts to replicate the behaviour documented for cfmakeraw in
|
// This attempts to replicate the behaviour documented for cfmakeraw in
|
||||||
// the termios(3) manpage.
|
// the termios(3) manpage.
|
||||||
newState.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
|
termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
|
||||||
newState.Oflag &^= syscall.OPOST
|
termios.Oflag &^= unix.OPOST
|
||||||
newState.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
|
termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
|
||||||
newState.Cflag &^= syscall.CSIZE | syscall.PARENB
|
termios.Cflag &^= unix.CSIZE | unix.PARENB
|
||||||
newState.Cflag |= syscall.CS8
|
termios.Cflag |= unix.CS8
|
||||||
newState.Cc[unix.VMIN] = 1
|
termios.Cc[unix.VMIN] = 1
|
||||||
newState.Cc[unix.VTIME] = 0
|
termios.Cc[unix.VTIME] = 0
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
|
if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,59 +61,55 @@ func MakeRaw(fd int) (*State, error) {
|
||||||
// GetState returns the current state of a terminal which may be useful to
|
// GetState returns the current state of a terminal which may be useful to
|
||||||
// restore the terminal after a signal.
|
// restore the terminal after a signal.
|
||||||
func GetState(fd int) (*State, error) {
|
func GetState(fd int) (*State, error) {
|
||||||
var oldState State
|
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &oldState, nil
|
return &State{termios: *termios}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore restores the terminal connected to the given file descriptor to a
|
// Restore restores the terminal connected to the given file descriptor to a
|
||||||
// previous state.
|
// previous state.
|
||||||
func Restore(fd int, state *State) error {
|
func Restore(fd int, state *State) error {
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0); err != 0 {
|
return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSize returns the dimensions of the given terminal.
|
// GetSize returns the dimensions of the given terminal.
|
||||||
func GetSize(fd int) (width, height int, err error) {
|
func GetSize(fd int) (width, height int, err error) {
|
||||||
var dimensions [4]uint16
|
ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
|
||||||
|
if err != nil {
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 {
|
|
||||||
return -1, -1, err
|
return -1, -1, err
|
||||||
}
|
}
|
||||||
return int(dimensions[1]), int(dimensions[0]), nil
|
return int(ws.Col), int(ws.Row), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// passwordReader is an io.Reader that reads from a specific file descriptor.
|
// passwordReader is an io.Reader that reads from a specific file descriptor.
|
||||||
type passwordReader int
|
type passwordReader int
|
||||||
|
|
||||||
func (r passwordReader) Read(buf []byte) (int, error) {
|
func (r passwordReader) Read(buf []byte) (int, error) {
|
||||||
return syscall.Read(int(r), buf)
|
return unix.Read(int(r), buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadPassword reads a line of input from a terminal without local echo. This
|
// ReadPassword reads a line of input from a terminal without local echo. This
|
||||||
// is commonly used for inputting passwords and other sensitive data. The slice
|
// is commonly used for inputting passwords and other sensitive data. The slice
|
||||||
// returned does not include the \n.
|
// returned does not include the \n.
|
||||||
func ReadPassword(fd int) ([]byte, error) {
|
func ReadPassword(fd int) ([]byte, error) {
|
||||||
var oldState syscall.Termios
|
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
newState := oldState
|
newState := *termios
|
||||||
newState.Lflag &^= syscall.ECHO
|
newState.Lflag &^= unix.ECHO
|
||||||
newState.Lflag |= syscall.ICANON | syscall.ISIG
|
newState.Lflag |= unix.ICANON | unix.ISIG
|
||||||
newState.Iflag |= syscall.ICRNL
|
newState.Iflag |= unix.ICRNL
|
||||||
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
|
if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0)
|
unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return readPasswordLine(passwordReader(fd))
|
return readPasswordLine(passwordReader(fd))
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
package terminal
|
package terminal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -71,13 +73,6 @@ func GetSize(fd int) (width, height int, err error) {
|
||||||
return int(info.Size.X), int(info.Size.Y), nil
|
return int(info.Size.X), int(info.Size.Y), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// passwordReader is an io.Reader that reads from a specific Windows HANDLE.
|
|
||||||
type passwordReader int
|
|
||||||
|
|
||||||
func (r passwordReader) Read(buf []byte) (int, error) {
|
|
||||||
return windows.Read(windows.Handle(r), buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadPassword reads a line of input from a terminal without local echo. This
|
// ReadPassword reads a line of input from a terminal without local echo. This
|
||||||
// is commonly used for inputting passwords and other sensitive data. The slice
|
// is commonly used for inputting passwords and other sensitive data. The slice
|
||||||
// returned does not include the \n.
|
// returned does not include the \n.
|
||||||
|
@ -98,5 +93,5 @@ func ReadPassword(fd int) ([]byte, error) {
|
||||||
windows.SetConsoleMode(windows.Handle(fd), old)
|
windows.SetConsoleMode(windows.Handle(fd), old)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return readPasswordLine(passwordReader(fd))
|
return readPasswordLine(os.NewFile(uintptr(fd), "stdin"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ func ControlMessageSpace(dataLen int) int {
|
||||||
type ControlMessage []byte
|
type ControlMessage []byte
|
||||||
|
|
||||||
// Data returns the data field of the control message at the head on
|
// Data returns the data field of the control message at the head on
|
||||||
// w.
|
// m.
|
||||||
func (m ControlMessage) Data(dataLen int) []byte {
|
func (m ControlMessage) Data(dataLen int) []byte {
|
||||||
l := controlHeaderLen()
|
l := controlHeaderLen()
|
||||||
if len(m) < l || len(m) < l+dataLen {
|
if len(m) < l || len(m) < l+dataLen {
|
||||||
|
@ -119,7 +119,7 @@ func (m ControlMessage) Data(dataLen int) []byte {
|
||||||
return m[l : l+dataLen]
|
return m[l : l+dataLen]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the control message at the next on w.
|
// Next returns the control message at the next on m.
|
||||||
//
|
//
|
||||||
// Next works only for standard control messages.
|
// Next works only for standard control messages.
|
||||||
func (m ControlMessage) Next(dataLen int) ControlMessage {
|
func (m ControlMessage) Next(dataLen int) ControlMessage {
|
||||||
|
@ -131,7 +131,7 @@ func (m ControlMessage) Next(dataLen int) ControlMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalHeader marshals the header fields of the control message at
|
// MarshalHeader marshals the header fields of the control message at
|
||||||
// the head on w.
|
// the head on m.
|
||||||
func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
|
func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
|
||||||
if len(m) < controlHeaderLen() {
|
if len(m) < controlHeaderLen() {
|
||||||
return errors.New("short message")
|
return errors.New("short message")
|
||||||
|
@ -142,7 +142,7 @@ func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseHeader parses and returns the header fields of the control
|
// ParseHeader parses and returns the header fields of the control
|
||||||
// message at the head on w.
|
// message at the head on m.
|
||||||
func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
|
func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
|
||||||
l := controlHeaderLen()
|
l := controlHeaderLen()
|
||||||
if len(m) < l {
|
if len(m) < l {
|
||||||
|
@ -152,7 +152,7 @@ func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
|
||||||
return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
|
return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal marshals the control message at the head on w, and returns
|
// Marshal marshals the control message at the head on m, and returns
|
||||||
// the next control message.
|
// the next control message.
|
||||||
func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
|
func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
|
||||||
l := len(data)
|
l := len(data)
|
||||||
|
@ -167,7 +167,7 @@ func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, erro
|
||||||
return m.Next(l), nil
|
return m.Next(l), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse parses w as a single or multiple control messages.
|
// Parse parses m as a single or multiple control messages.
|
||||||
//
|
//
|
||||||
// Parse works for both standard and compatible messages.
|
// Parse works for both standard and compatible messages.
|
||||||
func (m ControlMessage) Parse() ([]ControlMessage, error) {
|
func (m ControlMessage) Parse() ([]ControlMessage, error) {
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
// Created by cgo -godefs - DO NOT EDIT
|
||||||
|
// cgo -godefs defs_darwin.go
|
||||||
|
|
||||||
|
package socket
|
||||||
|
|
||||||
|
const (
|
||||||
|
sysAF_UNSPEC = 0x0
|
||||||
|
sysAF_INET = 0x2
|
||||||
|
sysAF_INET6 = 0x1e
|
||||||
|
|
||||||
|
sysSOCK_RAW = 0x3
|
||||||
|
)
|
||||||
|
|
||||||
|
type iovec struct {
|
||||||
|
Base *byte
|
||||||
|
Len uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type msghdr struct {
|
||||||
|
Name *byte
|
||||||
|
Namelen uint32
|
||||||
|
Pad_cgo_0 [4]byte
|
||||||
|
Iov *iovec
|
||||||
|
Iovlen int32
|
||||||
|
Pad_cgo_1 [4]byte
|
||||||
|
Control *byte
|
||||||
|
Controllen uint32
|
||||||
|
Flags int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type cmsghdr struct {
|
||||||
|
Len uint32
|
||||||
|
Level int32
|
||||||
|
Type int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type sockaddrInet struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Addr [4]byte /* in_addr */
|
||||||
|
Zero [8]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type sockaddrInet6 struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
sizeofIovec = 0x10
|
||||||
|
sizeofMsghdr = 0x30
|
||||||
|
sizeofCmsghdr = 0xc
|
||||||
|
|
||||||
|
sizeofSockaddrInet = 0x10
|
||||||
|
sizeofSockaddrInet6 = 0x1c
|
||||||
|
)
|
|
@ -0,0 +1,124 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// CPU affinity functions
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const cpuSetSize = _CPU_SETSIZE / _NCPUBITS
|
||||||
|
|
||||||
|
// CPUSet represents a CPU affinity mask.
|
||||||
|
type CPUSet [cpuSetSize]cpuMask
|
||||||
|
|
||||||
|
func schedAffinity(trap uintptr, pid int, set *CPUSet) error {
|
||||||
|
_, _, e := RawSyscall(trap, uintptr(pid), uintptr(unsafe.Sizeof(set)), uintptr(unsafe.Pointer(set)))
|
||||||
|
if e != 0 {
|
||||||
|
return errnoErr(e)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedGetaffinity gets the CPU affinity mask of the thread specified by pid.
|
||||||
|
// If pid is 0 the calling thread is used.
|
||||||
|
func SchedGetaffinity(pid int, set *CPUSet) error {
|
||||||
|
return schedAffinity(SYS_SCHED_GETAFFINITY, pid, set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedSetaffinity sets the CPU affinity mask of the thread specified by pid.
|
||||||
|
// If pid is 0 the calling thread is used.
|
||||||
|
func SchedSetaffinity(pid int, set *CPUSet) error {
|
||||||
|
return schedAffinity(SYS_SCHED_SETAFFINITY, pid, set)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zero clears the set s, so that it contains no CPUs.
|
||||||
|
func (s *CPUSet) Zero() {
|
||||||
|
for i := range s {
|
||||||
|
s[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cpuBitsIndex(cpu int) int {
|
||||||
|
return cpu / _NCPUBITS
|
||||||
|
}
|
||||||
|
|
||||||
|
func cpuBitsMask(cpu int) cpuMask {
|
||||||
|
return cpuMask(1 << (uint(cpu) % _NCPUBITS))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set adds cpu to the set s.
|
||||||
|
func (s *CPUSet) Set(cpu int) {
|
||||||
|
i := cpuBitsIndex(cpu)
|
||||||
|
if i < len(s) {
|
||||||
|
s[i] |= cpuBitsMask(cpu)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes cpu from the set s.
|
||||||
|
func (s *CPUSet) Clear(cpu int) {
|
||||||
|
i := cpuBitsIndex(cpu)
|
||||||
|
if i < len(s) {
|
||||||
|
s[i] &^= cpuBitsMask(cpu)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet reports whether cpu is in the set s.
|
||||||
|
func (s *CPUSet) IsSet(cpu int) bool {
|
||||||
|
i := cpuBitsIndex(cpu)
|
||||||
|
if i < len(s) {
|
||||||
|
return s[i]&cpuBitsMask(cpu) != 0
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count returns the number of CPUs in the set s.
|
||||||
|
func (s *CPUSet) Count() int {
|
||||||
|
c := 0
|
||||||
|
for _, b := range s {
|
||||||
|
c += onesCount64(uint64(b))
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// onesCount64 is a copy of Go 1.9's math/bits.OnesCount64.
|
||||||
|
// Once this package can require Go 1.9, we can delete this
|
||||||
|
// and update the caller to use bits.OnesCount64.
|
||||||
|
func onesCount64(x uint64) int {
|
||||||
|
const m0 = 0x5555555555555555 // 01010101 ...
|
||||||
|
const m1 = 0x3333333333333333 // 00110011 ...
|
||||||
|
const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ...
|
||||||
|
const m3 = 0x00ff00ff00ff00ff // etc.
|
||||||
|
const m4 = 0x0000ffff0000ffff
|
||||||
|
|
||||||
|
// Implementation: Parallel summing of adjacent bits.
|
||||||
|
// See "Hacker's Delight", Chap. 5: Counting Bits.
|
||||||
|
// The following pattern shows the general approach:
|
||||||
|
//
|
||||||
|
// x = x>>1&(m0&m) + x&(m0&m)
|
||||||
|
// x = x>>2&(m1&m) + x&(m1&m)
|
||||||
|
// x = x>>4&(m2&m) + x&(m2&m)
|
||||||
|
// x = x>>8&(m3&m) + x&(m3&m)
|
||||||
|
// x = x>>16&(m4&m) + x&(m4&m)
|
||||||
|
// x = x>>32&(m5&m) + x&(m5&m)
|
||||||
|
// return int(x)
|
||||||
|
//
|
||||||
|
// Masking (& operations) can be left away when there's no
|
||||||
|
// danger that a field's sum will carry over into the next
|
||||||
|
// field: Since the result cannot be > 64, 8 bits is enough
|
||||||
|
// and we can ignore the masks for the shifts by 8 and up.
|
||||||
|
// Per "Hacker's Delight", the first line can be simplified
|
||||||
|
// more, but it saves at best one instruction, so we leave
|
||||||
|
// it alone for clarity.
|
||||||
|
const m = 1<<64 - 1
|
||||||
|
x = x>>1&(m0&m) + x&(m0&m)
|
||||||
|
x = x>>2&(m1&m) + x&(m1&m)
|
||||||
|
x = (x>>4 + x) & (m2 & m)
|
||||||
|
x += x >> 8
|
||||||
|
x += x >> 16
|
||||||
|
x += x >> 32
|
||||||
|
return int(x) & (1<<7 - 1)
|
||||||
|
}
|
|
@ -10,6 +10,10 @@
|
||||||
// System calls for 386, Linux
|
// System calls for 386, Linux
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// See ../runtime/sys_linux_386.s for the reason why we always use int 0x80
|
||||||
|
// instead of the glibc-specific "CALL 0x10(GS)".
|
||||||
|
#define INVOKE_SYSCALL INT $0x80
|
||||||
|
|
||||||
// Just jump to package syscall's implementation for all these functions.
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
// The runtime may know about them.
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
@ -19,12 +23,38 @@ TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||||
JMP syscall·Syscall6(SB)
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
CALL runtime·entersyscall(SB)
|
||||||
|
MOVL trap+0(FP), AX // syscall entry
|
||||||
|
MOVL a1+4(FP), BX
|
||||||
|
MOVL a2+8(FP), CX
|
||||||
|
MOVL a3+12(FP), DX
|
||||||
|
MOVL $0, SI
|
||||||
|
MOVL $0, DI
|
||||||
|
INVOKE_SYSCALL
|
||||||
|
MOVL AX, r1+16(FP)
|
||||||
|
MOVL DX, r2+20(FP)
|
||||||
|
CALL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||||
JMP syscall·RawSyscall(SB)
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||||
JMP syscall·RawSyscall6(SB)
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
MOVL trap+0(FP), AX // syscall entry
|
||||||
|
MOVL a1+4(FP), BX
|
||||||
|
MOVL a2+8(FP), CX
|
||||||
|
MOVL a3+12(FP), DX
|
||||||
|
MOVL $0, SI
|
||||||
|
MOVL $0, DI
|
||||||
|
INVOKE_SYSCALL
|
||||||
|
MOVL AX, r1+16(FP)
|
||||||
|
MOVL DX, r2+20(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT ·socketcall(SB),NOSPLIT,$0-36
|
TEXT ·socketcall(SB),NOSPLIT,$0-36
|
||||||
JMP syscall·socketcall(SB)
|
JMP syscall·socketcall(SB)
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,39 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
JMP syscall·Syscall6(SB)
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
CALL runtime·entersyscall(SB)
|
||||||
|
MOVQ a1+8(FP), DI
|
||||||
|
MOVQ a2+16(FP), SI
|
||||||
|
MOVQ a3+24(FP), DX
|
||||||
|
MOVQ $0, R10
|
||||||
|
MOVQ $0, R8
|
||||||
|
MOVQ $0, R9
|
||||||
|
MOVQ trap+0(FP), AX // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVQ AX, r1+32(FP)
|
||||||
|
MOVQ DX, r2+40(FP)
|
||||||
|
CALL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
JMP syscall·RawSyscall(SB)
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
JMP syscall·RawSyscall6(SB)
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVQ a1+8(FP), DI
|
||||||
|
MOVQ a2+16(FP), SI
|
||||||
|
MOVQ a3+24(FP), DX
|
||||||
|
MOVQ $0, R10
|
||||||
|
MOVQ $0, R8
|
||||||
|
MOVQ $0, R9
|
||||||
|
MOVQ trap+0(FP), AX // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVQ AX, r1+32(FP)
|
||||||
|
MOVQ DX, r2+40(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT ·gettimeofday(SB),NOSPLIT,$0-16
|
TEXT ·gettimeofday(SB),NOSPLIT,$0-16
|
||||||
JMP syscall·gettimeofday(SB)
|
JMP syscall·gettimeofday(SB)
|
||||||
|
|
|
@ -19,11 +19,38 @@ TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||||
B syscall·Syscall6(SB)
|
B syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVW trap+0(FP), R7
|
||||||
|
MOVW a1+4(FP), R0
|
||||||
|
MOVW a2+8(FP), R1
|
||||||
|
MOVW a3+12(FP), R2
|
||||||
|
MOVW $0, R3
|
||||||
|
MOVW $0, R4
|
||||||
|
MOVW $0, R5
|
||||||
|
SWI $0
|
||||||
|
MOVW R0, r1+16(FP)
|
||||||
|
MOVW $0, R0
|
||||||
|
MOVW R0, r2+20(FP)
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||||
B syscall·RawSyscall(SB)
|
B syscall·RawSyscall(SB)
|
||||||
|
|
||||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||||
B syscall·RawSyscall6(SB)
|
B syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
TEXT ·seek(SB),NOSPLIT,$0-32
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
MOVW trap+0(FP), R7 // syscall entry
|
||||||
|
MOVW a1+4(FP), R0
|
||||||
|
MOVW a2+8(FP), R1
|
||||||
|
MOVW a3+12(FP), R2
|
||||||
|
SWI $0
|
||||||
|
MOVW R0, r1+16(FP)
|
||||||
|
MOVW $0, R0
|
||||||
|
MOVW R0, r2+20(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·seek(SB),NOSPLIT,$0-28
|
||||||
B syscall·seek(SB)
|
B syscall·seek(SB)
|
||||||
|
|
|
@ -17,8 +17,36 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
B syscall·Syscall6(SB)
|
B syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R0
|
||||||
|
MOVD a2+16(FP), R1
|
||||||
|
MOVD a3+24(FP), R2
|
||||||
|
MOVD $0, R3
|
||||||
|
MOVD $0, R4
|
||||||
|
MOVD $0, R5
|
||||||
|
MOVD trap+0(FP), R8 // syscall entry
|
||||||
|
SVC
|
||||||
|
MOVD R0, r1+32(FP) // r1
|
||||||
|
MOVD R1, r2+40(FP) // r2
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
B syscall·RawSyscall(SB)
|
B syscall·RawSyscall(SB)
|
||||||
|
|
||||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
B syscall·RawSyscall6(SB)
|
B syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVD a1+8(FP), R0
|
||||||
|
MOVD a2+16(FP), R1
|
||||||
|
MOVD a3+24(FP), R2
|
||||||
|
MOVD $0, R3
|
||||||
|
MOVD $0, R4
|
||||||
|
MOVD $0, R5
|
||||||
|
MOVD trap+0(FP), R8 // syscall entry
|
||||||
|
SVC
|
||||||
|
MOVD R0, r1+32(FP)
|
||||||
|
MOVD R1, r2+40(FP)
|
||||||
|
RET
|
||||||
|
|
|
@ -21,8 +21,36 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
JMP syscall·Syscall6(SB)
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
JAL runtime·entersyscall(SB)
|
||||||
|
MOVV a1+8(FP), R4
|
||||||
|
MOVV a2+16(FP), R5
|
||||||
|
MOVV a3+24(FP), R6
|
||||||
|
MOVV R0, R7
|
||||||
|
MOVV R0, R8
|
||||||
|
MOVV R0, R9
|
||||||
|
MOVV trap+0(FP), R2 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVV R2, r1+32(FP)
|
||||||
|
MOVV R3, r2+40(FP)
|
||||||
|
JAL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
JMP syscall·RawSyscall(SB)
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
JMP syscall·RawSyscall6(SB)
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVV a1+8(FP), R4
|
||||||
|
MOVV a2+16(FP), R5
|
||||||
|
MOVV a3+24(FP), R6
|
||||||
|
MOVV R0, R7
|
||||||
|
MOVV R0, R8
|
||||||
|
MOVV R0, R9
|
||||||
|
MOVV trap+0(FP), R2 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVV R2, r1+32(FP)
|
||||||
|
MOVV R3, r2+40(FP)
|
||||||
|
RET
|
||||||
|
|
|
@ -24,8 +24,31 @@ TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||||
JMP syscall·Syscall9(SB)
|
JMP syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
JAL runtime·entersyscall(SB)
|
||||||
|
MOVW a1+4(FP), R4
|
||||||
|
MOVW a2+8(FP), R5
|
||||||
|
MOVW a3+12(FP), R6
|
||||||
|
MOVW R0, R7
|
||||||
|
MOVW trap+0(FP), R2 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVW R2, r1+16(FP) // r1
|
||||||
|
MOVW R3, r2+20(FP) // r2
|
||||||
|
JAL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||||
JMP syscall·RawSyscall(SB)
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||||
JMP syscall·RawSyscall6(SB)
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-24
|
||||||
|
MOVW a1+4(FP), R4
|
||||||
|
MOVW a2+8(FP), R5
|
||||||
|
MOVW a3+12(FP), R6
|
||||||
|
MOVW trap+0(FP), R2 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVW R2, r1+16(FP)
|
||||||
|
MOVW R3, r2+20(FP)
|
||||||
|
RET
|
||||||
|
|
|
@ -21,8 +21,36 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
BR syscall·Syscall6(SB)
|
BR syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R3
|
||||||
|
MOVD a2+16(FP), R4
|
||||||
|
MOVD a3+24(FP), R5
|
||||||
|
MOVD R0, R6
|
||||||
|
MOVD R0, R7
|
||||||
|
MOVD R0, R8
|
||||||
|
MOVD trap+0(FP), R9 // syscall entry
|
||||||
|
SYSCALL R9
|
||||||
|
MOVD R3, r1+32(FP)
|
||||||
|
MOVD R4, r2+40(FP)
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
BR syscall·RawSyscall(SB)
|
BR syscall·RawSyscall(SB)
|
||||||
|
|
||||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
BR syscall·RawSyscall6(SB)
|
BR syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVD a1+8(FP), R3
|
||||||
|
MOVD a2+16(FP), R4
|
||||||
|
MOVD a3+24(FP), R5
|
||||||
|
MOVD R0, R6
|
||||||
|
MOVD R0, R7
|
||||||
|
MOVD R0, R8
|
||||||
|
MOVD trap+0(FP), R9 // syscall entry
|
||||||
|
SYSCALL R9
|
||||||
|
MOVD R3, r1+32(FP)
|
||||||
|
MOVD R4, r2+40(FP)
|
||||||
|
RET
|
||||||
|
|
|
@ -21,8 +21,36 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
BR syscall·Syscall6(SB)
|
BR syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R2
|
||||||
|
MOVD a2+16(FP), R3
|
||||||
|
MOVD a3+24(FP), R4
|
||||||
|
MOVD $0, R5
|
||||||
|
MOVD $0, R6
|
||||||
|
MOVD $0, R7
|
||||||
|
MOVD trap+0(FP), R1 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVD R2, r1+32(FP)
|
||||||
|
MOVD R3, r2+40(FP)
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
BR syscall·RawSyscall(SB)
|
BR syscall·RawSyscall(SB)
|
||||||
|
|
||||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
BR syscall·RawSyscall6(SB)
|
BR syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOVD a1+8(FP), R2
|
||||||
|
MOVD a2+16(FP), R3
|
||||||
|
MOVD a3+24(FP), R4
|
||||||
|
MOVD $0, R5
|
||||||
|
MOVD $0, R6
|
||||||
|
MOVD $0, R7
|
||||||
|
MOVD trap+0(FP), R1 // syscall entry
|
||||||
|
SYSCALL
|
||||||
|
MOVD R2, r1+32(FP)
|
||||||
|
MOVD R3, r2+40(FP)
|
||||||
|
RET
|
||||||
|
|
|
@ -6,97 +6,12 @@
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
import "unsafe"
|
import "syscall"
|
||||||
|
|
||||||
// readInt returns the size-bytes unsigned integer in native byte order at offset off.
|
|
||||||
func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
|
|
||||||
if len(b) < int(off+size) {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
if isBigEndian {
|
|
||||||
return readIntBE(b[off:], size), true
|
|
||||||
}
|
|
||||||
return readIntLE(b[off:], size), true
|
|
||||||
}
|
|
||||||
|
|
||||||
func readIntBE(b []byte, size uintptr) uint64 {
|
|
||||||
switch size {
|
|
||||||
case 1:
|
|
||||||
return uint64(b[0])
|
|
||||||
case 2:
|
|
||||||
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
|
|
||||||
return uint64(b[1]) | uint64(b[0])<<8
|
|
||||||
case 4:
|
|
||||||
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
|
|
||||||
return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24
|
|
||||||
case 8:
|
|
||||||
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
|
|
||||||
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
|
|
||||||
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
|
|
||||||
default:
|
|
||||||
panic("syscall: readInt with unsupported size")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func readIntLE(b []byte, size uintptr) uint64 {
|
|
||||||
switch size {
|
|
||||||
case 1:
|
|
||||||
return uint64(b[0])
|
|
||||||
case 2:
|
|
||||||
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
|
|
||||||
return uint64(b[0]) | uint64(b[1])<<8
|
|
||||||
case 4:
|
|
||||||
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
|
|
||||||
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24
|
|
||||||
case 8:
|
|
||||||
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
|
|
||||||
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
|
|
||||||
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
|
|
||||||
default:
|
|
||||||
panic("syscall: readInt with unsupported size")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseDirent parses up to max directory entries in buf,
|
// ParseDirent parses up to max directory entries in buf,
|
||||||
// appending the names to names. It returns the number of
|
// appending the names to names. It returns the number of
|
||||||
// bytes consumed from buf, the number of entries added
|
// bytes consumed from buf, the number of entries added
|
||||||
// to names, and the new names slice.
|
// to names, and the new names slice.
|
||||||
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
|
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
|
||||||
origlen := len(buf)
|
return syscall.ParseDirent(buf, max, names)
|
||||||
count = 0
|
|
||||||
for max != 0 && len(buf) > 0 {
|
|
||||||
reclen, ok := direntReclen(buf)
|
|
||||||
if !ok || reclen > uint64(len(buf)) {
|
|
||||||
return origlen, count, names
|
|
||||||
}
|
|
||||||
rec := buf[:reclen]
|
|
||||||
buf = buf[reclen:]
|
|
||||||
ino, ok := direntIno(rec)
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if ino == 0 { // File absent in directory.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))
|
|
||||||
namlen, ok := direntNamlen(rec)
|
|
||||||
if !ok || namoff+namlen > uint64(len(rec)) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
name := rec[namoff : namoff+namlen]
|
|
||||||
for i, c := range name {
|
|
||||||
if c == 0 {
|
|
||||||
name = name[:i]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check for useless names before allocating a string.
|
|
||||||
if string(name) == "." || string(name) == ".." {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
max--
|
|
||||||
count++
|
|
||||||
names = append(names, string(name))
|
|
||||||
}
|
|
||||||
return origlen - len(buf), count, names
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,3 +25,7 @@ func Clearenv() {
|
||||||
func Environ() []string {
|
func Environ() []string {
|
||||||
return syscall.Environ()
|
return syscall.Environ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Unsetenv(key string) error {
|
||||||
|
return syscall.Unsetenv(key)
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build go1.4
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
import "syscall"
|
|
||||||
|
|
||||||
func Unsetenv(key string) error {
|
|
||||||
// This was added in Go 1.4.
|
|
||||||
return syscall.Unsetenv(key)
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FIXME: unexported function from os
|
|
||||||
// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
|
|
||||||
func syscallMode(i os.FileMode) (o uint32) {
|
|
||||||
o |= uint32(i.Perm())
|
|
||||||
if i&os.ModeSetuid != 0 {
|
|
||||||
o |= syscall.S_ISUID
|
|
||||||
}
|
|
||||||
if i&os.ModeSetgid != 0 {
|
|
||||||
o |= syscall.S_ISGID
|
|
||||||
}
|
|
||||||
if i&os.ModeSticky != 0 {
|
|
||||||
o |= syscall.S_ISVTX
|
|
||||||
}
|
|
||||||
// No mapping for Go's ModeTemporary (plan9 only).
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -11,9 +11,19 @@ import "syscall"
|
||||||
// We can't use the gc-syntax .s files for gccgo. On the plus side
|
// We can't use the gc-syntax .s files for gccgo. On the plus side
|
||||||
// much of the functionality can be written directly in Go.
|
// much of the functionality can be written directly in Go.
|
||||||
|
|
||||||
|
//extern gccgoRealSyscallNoError
|
||||||
|
func realSyscallNoError(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r uintptr)
|
||||||
|
|
||||||
//extern gccgoRealSyscall
|
//extern gccgoRealSyscall
|
||||||
func realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r, errno uintptr)
|
func realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r, errno uintptr)
|
||||||
|
|
||||||
|
func SyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) {
|
||||||
|
syscall.Entersyscall()
|
||||||
|
r := realSyscallNoError(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
|
||||||
|
syscall.Exitsyscall()
|
||||||
|
return r, 0
|
||||||
|
}
|
||||||
|
|
||||||
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
||||||
syscall.Entersyscall()
|
syscall.Entersyscall()
|
||||||
r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
|
r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
|
||||||
|
@ -35,6 +45,11 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
|
||||||
return r, 0, syscall.Errno(errno)
|
return r, 0, syscall.Errno(errno)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) {
|
||||||
|
r := realSyscallNoError(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
|
||||||
|
return r, 0
|
||||||
|
}
|
||||||
|
|
||||||
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
||||||
r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
|
r, errno := realSyscall(trap, a1, a2, a3, 0, 0, 0, 0, 0, 0)
|
||||||
return r, 0, syscall.Errno(errno)
|
return r, 0, syscall.Errno(errno)
|
||||||
|
|
|
@ -31,6 +31,12 @@ gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintp
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uintptr_t
|
||||||
|
gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
|
||||||
|
{
|
||||||
|
return syscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9);
|
||||||
|
}
|
||||||
|
|
||||||
// Define the use function in C so that it is not inlined.
|
// Define the use function in C so that it is not inlined.
|
||||||
|
|
||||||
extern void use(void *) __asm__ (GOSYM_PREFIX GOPKGPATH ".use") __attribute__((noinline));
|
extern void use(void *) __asm__ (GOSYM_PREFIX GOPKGPATH ".use") __attribute__((noinline));
|
||||||
|
|
|
@ -80,12 +80,6 @@ darwin_arm64)
|
||||||
mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
|
mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
;;
|
;;
|
||||||
dragonfly_386)
|
|
||||||
mkerrors="$mkerrors -m32"
|
|
||||||
mksyscall="./mksyscall.pl -l32 -dragonfly"
|
|
||||||
mksysnum="curl -s 'http://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master' | ./mksysnum_dragonfly.pl"
|
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
|
||||||
;;
|
|
||||||
dragonfly_amd64)
|
dragonfly_amd64)
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
mksyscall="./mksyscall.pl -dragonfly"
|
mksyscall="./mksyscall.pl -dragonfly"
|
||||||
|
|
|
@ -38,6 +38,8 @@ includes_Darwin='
|
||||||
#define _DARWIN_C_SOURCE
|
#define _DARWIN_C_SOURCE
|
||||||
#define KERNEL
|
#define KERNEL
|
||||||
#define _DARWIN_USE_64_BIT_INODE
|
#define _DARWIN_USE_64_BIT_INODE
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/attr.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/event.h>
|
#include <sys/event.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
|
@ -46,6 +48,7 @@ includes_Darwin='
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <net/bpf.h>
|
#include <net/bpf.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
@ -184,6 +187,7 @@ struct ltchars {
|
||||||
#include <linux/vm_sockets.h>
|
#include <linux/vm_sockets.h>
|
||||||
#include <linux/taskstats.h>
|
#include <linux/taskstats.h>
|
||||||
#include <linux/genetlink.h>
|
#include <linux/genetlink.h>
|
||||||
|
#include <linux/stat.h>
|
||||||
#include <linux/watchdog.h>
|
#include <linux/watchdog.h>
|
||||||
#include <net/route.h>
|
#include <net/route.h>
|
||||||
#include <asm/termbits.h>
|
#include <asm/termbits.h>
|
||||||
|
@ -384,7 +388,9 @@ ccflags="$@"
|
||||||
$2 == "SOMAXCONN" ||
|
$2 == "SOMAXCONN" ||
|
||||||
$2 == "NAME_MAX" ||
|
$2 == "NAME_MAX" ||
|
||||||
$2 == "IFNAMSIZ" ||
|
$2 == "IFNAMSIZ" ||
|
||||||
$2 ~ /^CTL_(MAXNAME|NET|QUERY)$/ ||
|
$2 ~ /^CTL_(HW|KERN|MAXNAME|NET|QUERY)$/ ||
|
||||||
|
$2 ~ /^KERN_(HOSTNAME|OS(RELEASE|TYPE)|VERSION)$/ ||
|
||||||
|
$2 ~ /^HW_MACHINE$/ ||
|
||||||
$2 ~ /^SYSCTL_VERS/ ||
|
$2 ~ /^SYSCTL_VERS/ ||
|
||||||
$2 ~ /^(MS|MNT|UMOUNT)_/ ||
|
$2 ~ /^(MS|MNT|UMOUNT)_/ ||
|
||||||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
|
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
|
||||||
|
@ -419,10 +425,15 @@ ccflags="$@"
|
||||||
$2 ~ /^SECCOMP_MODE_/ ||
|
$2 ~ /^SECCOMP_MODE_/ ||
|
||||||
$2 ~ /^SPLICE_/ ||
|
$2 ~ /^SPLICE_/ ||
|
||||||
$2 ~ /^(VM|VMADDR)_/ ||
|
$2 ~ /^(VM|VMADDR)_/ ||
|
||||||
|
$2 ~ /^IOCTL_VM_SOCKETS_/ ||
|
||||||
$2 ~ /^(TASKSTATS|TS)_/ ||
|
$2 ~ /^(TASKSTATS|TS)_/ ||
|
||||||
|
$2 ~ /^CGROUPSTATS_/ ||
|
||||||
$2 ~ /^GENL_/ ||
|
$2 ~ /^GENL_/ ||
|
||||||
|
$2 ~ /^STATX_/ ||
|
||||||
$2 ~ /^UTIME_/ ||
|
$2 ~ /^UTIME_/ ||
|
||||||
$2 ~ /^XATTR_(CREATE|REPLACE)/ ||
|
$2 ~ /^XATTR_(CREATE|REPLACE)/ ||
|
||||||
|
$2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ ||
|
||||||
|
$2 ~ /^FSOPT_/ ||
|
||||||
$2 ~ /^WDIOC_/ ||
|
$2 ~ /^WDIOC_/ ||
|
||||||
$2 !~ "WMESGLEN" &&
|
$2 !~ "WMESGLEN" &&
|
||||||
$2 ~ /^W[A-Z0-9]+$/ ||
|
$2 ~ /^W[A-Z0-9]+$/ ||
|
||||||
|
|
|
@ -210,7 +210,15 @@ while(<>) {
|
||||||
# Determine which form to use; pad args with zeros.
|
# Determine which form to use; pad args with zeros.
|
||||||
my $asm = "Syscall";
|
my $asm = "Syscall";
|
||||||
if ($nonblock) {
|
if ($nonblock) {
|
||||||
|
if ($errvar ne "") {
|
||||||
$asm = "RawSyscall";
|
$asm = "RawSyscall";
|
||||||
|
} else {
|
||||||
|
$asm = "RawSyscallNoError";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($errvar eq "") {
|
||||||
|
$asm = "SyscallNoError";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(@args <= 3) {
|
if(@args <= 3) {
|
||||||
while(@args < 3) {
|
while(@args < 3) {
|
||||||
|
@ -284,7 +292,11 @@ while(<>) {
|
||||||
if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") {
|
if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") {
|
||||||
$text .= "\t$call\n";
|
$text .= "\t$call\n";
|
||||||
} else {
|
} else {
|
||||||
|
if ($errvar ne "") {
|
||||||
$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
|
$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
|
||||||
|
} else {
|
||||||
|
$text .= "\t$ret[0], $ret[1] := $call\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$text .= $body;
|
$text .= $body;
|
||||||
|
|
||||||
|
|
|
@ -352,6 +352,18 @@ func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) {
|
||||||
return &value, err
|
return &value, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetsockoptString returns the string value of the socket option opt for the
|
||||||
|
// socket associated with fd at the given socket level.
|
||||||
|
func GetsockoptString(fd, level, opt int) (string, error) {
|
||||||
|
buf := make([]byte, 256)
|
||||||
|
vallen := _Socklen(len(buf))
|
||||||
|
err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
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)
|
||||||
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
|
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
|
||||||
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
||||||
|
@ -570,7 +582,12 @@ func UtimesNano(path string, ts []Timespec) error {
|
||||||
if len(ts) != 2 {
|
if len(ts) != 2 {
|
||||||
return EINVAL
|
return EINVAL
|
||||||
}
|
}
|
||||||
err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
|
// Darwin setattrlist can set nanosecond timestamps
|
||||||
|
err := setattrlistTimes(path, ts, 0)
|
||||||
|
if err != ENOSYS {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
|
||||||
if err != ENOSYS {
|
if err != ENOSYS {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -590,6 +607,10 @@ func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error {
|
||||||
if len(ts) != 2 {
|
if len(ts) != 2 {
|
||||||
return EINVAL
|
return EINVAL
|
||||||
}
|
}
|
||||||
|
err := setattrlistTimes(path, ts, flags)
|
||||||
|
if err != ENOSYS {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
|
return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,18 +76,6 @@ func nametomib(name string) (mib []_C_int, err error) {
|
||||||
return buf[0 : n/siz], nil
|
return buf[0 : n/siz], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func direntIno(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntReclen(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntNamlen(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
|
||||||
}
|
|
||||||
|
|
||||||
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
|
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
|
||||||
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
|
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
|
||||||
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
|
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
|
||||||
|
@ -187,6 +175,37 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setattrlistTimes(path string, times []Timespec, flags int) error {
|
||||||
|
_p0, err := BytePtrFromString(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var attrList attrList
|
||||||
|
attrList.bitmapCount = ATTR_BIT_MAP_COUNT
|
||||||
|
attrList.CommonAttr = ATTR_CMN_MODTIME | ATTR_CMN_ACCTIME
|
||||||
|
|
||||||
|
// order is mtime, atime: the opposite of Chtimes
|
||||||
|
attributes := [2]Timespec{times[1], times[0]}
|
||||||
|
options := 0
|
||||||
|
if flags&AT_SYMLINK_NOFOLLOW != 0 {
|
||||||
|
options |= FSOPT_NOFOLLOW
|
||||||
|
}
|
||||||
|
_, _, e1 := Syscall6(
|
||||||
|
SYS_SETATTRLIST,
|
||||||
|
uintptr(unsafe.Pointer(_p0)),
|
||||||
|
uintptr(unsafe.Pointer(&attrList)),
|
||||||
|
uintptr(unsafe.Pointer(&attributes)),
|
||||||
|
uintptr(unsafe.Sizeof(attributes)),
|
||||||
|
uintptr(options),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
if e1 != 0 {
|
||||||
|
return e1
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func utimensat(dirfd int, path string, times *[2]Timespec, flags int) error {
|
func utimensat(dirfd int, path string, times *[2]Timespec, flags int) error {
|
||||||
// Darwin doesn't support SYS_UTIMENSAT
|
// Darwin doesn't support SYS_UTIMENSAT
|
||||||
return ENOSYS
|
return ENOSYS
|
||||||
|
@ -239,6 +258,52 @@ func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||||
return &value, err
|
return &value, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Uname(uname *Utsname) error {
|
||||||
|
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
|
||||||
|
n := unsafe.Sizeof(uname.Sysname)
|
||||||
|
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
|
||||||
|
n = unsafe.Sizeof(uname.Nodename)
|
||||||
|
if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
|
||||||
|
n = unsafe.Sizeof(uname.Release)
|
||||||
|
if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_VERSION}
|
||||||
|
n = unsafe.Sizeof(uname.Version)
|
||||||
|
if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The version might have newlines or tabs in it, convert them to
|
||||||
|
// spaces.
|
||||||
|
for i, b := range uname.Version {
|
||||||
|
if b == '\n' || b == '\t' {
|
||||||
|
if i == len(uname.Version)-1 {
|
||||||
|
uname.Version[i] = 0
|
||||||
|
} else {
|
||||||
|
uname.Version[i] = ' '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_HW, HW_MACHINE}
|
||||||
|
n = unsafe.Sizeof(uname.Machine)
|
||||||
|
if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exposed directly
|
* Exposed directly
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -60,3 +60,7 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||||
}
|
}
|
||||||
|
|
||||||
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic
|
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic
|
||||||
|
|
||||||
|
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
|
||||||
|
// of darwin/arm the syscall is called sysctl instead of __sysctl.
|
||||||
|
const SYS___SYSCTL = SYS_SYSCTL
|
||||||
|
|
|
@ -56,22 +56,6 @@ func nametomib(name string) (mib []_C_int, err error) {
|
||||||
return buf[0 : n/siz], nil
|
return buf[0 : n/siz], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func direntIno(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntReclen(buf []byte) (uint64, bool) {
|
|
||||||
namlen, ok := direntNamlen(buf)
|
|
||||||
if !ok {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
return (16 + namlen + 1 + 7) &^ 7, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntNamlen(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
|
||||||
}
|
|
||||||
|
|
||||||
//sysnb pipe() (r int, w int, err error)
|
//sysnb pipe() (r int, w int, err error)
|
||||||
|
|
||||||
func Pipe(p []int) (err error) {
|
func Pipe(p []int) (err error) {
|
||||||
|
@ -110,6 +94,23 @@ func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ImplementsGetwd = true
|
||||||
|
|
||||||
|
//sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD
|
||||||
|
|
||||||
|
func Getwd() (string, error) {
|
||||||
|
var buf [PathMax]byte
|
||||||
|
_, err := Getcwd(buf[0:])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
n := clen(buf[:])
|
||||||
|
if n < 1 {
|
||||||
|
return "", EINVAL
|
||||||
|
}
|
||||||
|
return string(buf[:n]), nil
|
||||||
|
}
|
||||||
|
|
||||||
func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||||
var _p0 unsafe.Pointer
|
var _p0 unsafe.Pointer
|
||||||
var bufsize uintptr
|
var bufsize uintptr
|
||||||
|
@ -125,6 +126,113 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setattrlistTimes(path string, times []Timespec, flags int) error {
|
||||||
|
// used on Darwin for UtimesNano
|
||||||
|
return ENOSYS
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
||||||
|
|
||||||
|
// ioctl itself should not be exposed directly, but additional get/set
|
||||||
|
// functions for specific types are permissible.
|
||||||
|
|
||||||
|
// IoctlSetInt performs an ioctl operation which sets an integer value
|
||||||
|
// on fd, using the specified request number.
|
||||||
|
func IoctlSetInt(fd int, req uint, value int) error {
|
||||||
|
return ioctl(fd, req, uintptr(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
|
||||||
|
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlSetTermios(fd int, req uint, value *Termios) error {
|
||||||
|
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlGetInt performs an ioctl operation which gets an integer value
|
||||||
|
// from fd, using the specified request number.
|
||||||
|
func IoctlGetInt(fd int, req uint) (int, error) {
|
||||||
|
var value int
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
||||||
|
var value Winsize
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||||
|
var value Termios
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func sysctlUname(mib []_C_int, old *byte, oldlen *uintptr) error {
|
||||||
|
err := sysctl(mib, old, oldlen, nil, 0)
|
||||||
|
if err != nil {
|
||||||
|
// Utsname members on Dragonfly are only 32 bytes and
|
||||||
|
// the syscall returns ENOMEM in case the actual value
|
||||||
|
// is longer.
|
||||||
|
if err == ENOMEM {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func Uname(uname *Utsname) error {
|
||||||
|
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
|
||||||
|
n := unsafe.Sizeof(uname.Sysname)
|
||||||
|
if err := sysctlUname(mib, &uname.Sysname[0], &n); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
uname.Sysname[unsafe.Sizeof(uname.Sysname)-1] = 0
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
|
||||||
|
n = unsafe.Sizeof(uname.Nodename)
|
||||||
|
if err := sysctlUname(mib, &uname.Nodename[0], &n); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
uname.Nodename[unsafe.Sizeof(uname.Nodename)-1] = 0
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
|
||||||
|
n = unsafe.Sizeof(uname.Release)
|
||||||
|
if err := sysctlUname(mib, &uname.Release[0], &n); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
uname.Release[unsafe.Sizeof(uname.Release)-1] = 0
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_VERSION}
|
||||||
|
n = unsafe.Sizeof(uname.Version)
|
||||||
|
if err := sysctlUname(mib, &uname.Version[0], &n); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The version might have newlines or tabs in it, convert them to
|
||||||
|
// spaces.
|
||||||
|
for i, b := range uname.Version {
|
||||||
|
if b == '\n' || b == '\t' {
|
||||||
|
if i == len(uname.Version)-1 {
|
||||||
|
uname.Version[i] = 0
|
||||||
|
} else {
|
||||||
|
uname.Version[i] = ' '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_HW, HW_MACHINE}
|
||||||
|
n = unsafe.Sizeof(uname.Machine)
|
||||||
|
if err := sysctlUname(mib, &uname.Machine[0], &n); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
uname.Machine[unsafe.Sizeof(uname.Machine)-1] = 0
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exposed directly
|
* Exposed directly
|
||||||
*/
|
*/
|
||||||
|
@ -225,7 +333,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||||
// Getlogin
|
// Getlogin
|
||||||
// Sigpending
|
// Sigpending
|
||||||
// Sigaltstack
|
// Sigaltstack
|
||||||
// Ioctl
|
|
||||||
// Reboot
|
// Reboot
|
||||||
// Execve
|
// Execve
|
||||||
// Vfork
|
// Vfork
|
||||||
|
|
|
@ -54,18 +54,6 @@ func nametomib(name string) (mib []_C_int, err error) {
|
||||||
return buf[0 : n/siz], nil
|
return buf[0 : n/siz], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func direntIno(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntReclen(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntNamlen(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
|
||||||
}
|
|
||||||
|
|
||||||
//sysnb pipe() (r int, w int, err error)
|
//sysnb pipe() (r int, w int, err error)
|
||||||
|
|
||||||
func Pipe(p []int) (err error) {
|
func Pipe(p []int) (err error) {
|
||||||
|
@ -105,6 +93,23 @@ func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ImplementsGetwd = true
|
||||||
|
|
||||||
|
//sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD
|
||||||
|
|
||||||
|
func Getwd() (string, error) {
|
||||||
|
var buf [PathMax]byte
|
||||||
|
_, err := Getcwd(buf[0:])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
n := clen(buf[:])
|
||||||
|
if n < 1 {
|
||||||
|
return "", EINVAL
|
||||||
|
}
|
||||||
|
return string(buf[:n]), nil
|
||||||
|
}
|
||||||
|
|
||||||
func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||||
var _p0 unsafe.Pointer
|
var _p0 unsafe.Pointer
|
||||||
var bufsize uintptr
|
var bufsize uintptr
|
||||||
|
@ -120,6 +125,11 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setattrlistTimes(path string, times []Timespec, flags int) error {
|
||||||
|
// used on Darwin for UtimesNano
|
||||||
|
return ENOSYS
|
||||||
|
}
|
||||||
|
|
||||||
// Derive extattr namespace and attribute name
|
// Derive extattr namespace and attribute name
|
||||||
|
|
||||||
func xattrnamespace(fullattr string) (ns int, attr string, err error) {
|
func xattrnamespace(fullattr string) (ns int, attr string, err error) {
|
||||||
|
@ -271,7 +281,6 @@ func Listxattr(file string, dest []byte) (sz int, err error) {
|
||||||
|
|
||||||
// FreeBSD won't allow you to list xattrs from multiple namespaces
|
// FreeBSD won't allow you to list xattrs from multiple namespaces
|
||||||
s := 0
|
s := 0
|
||||||
var e error
|
|
||||||
for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
|
for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
|
||||||
stmp, e := ExtattrListFile(file, nsid, uintptr(d), destsiz)
|
stmp, e := ExtattrListFile(file, nsid, uintptr(d), destsiz)
|
||||||
|
|
||||||
|
@ -283,7 +292,6 @@ func Listxattr(file string, dest []byte) (sz int, err error) {
|
||||||
* we don't have read permissions on, so don't ignore those errors
|
* we don't have read permissions on, so don't ignore those errors
|
||||||
*/
|
*/
|
||||||
if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
|
if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
|
||||||
e = nil
|
|
||||||
continue
|
continue
|
||||||
} else if e != nil {
|
} else if e != nil {
|
||||||
return s, e
|
return s, e
|
||||||
|
@ -297,7 +305,7 @@ func Listxattr(file string, dest []byte) (sz int, err error) {
|
||||||
d = initxattrdest(dest, s)
|
d = initxattrdest(dest, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, e
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Flistxattr(fd int, dest []byte) (sz int, err error) {
|
func Flistxattr(fd int, dest []byte) (sz int, err error) {
|
||||||
|
@ -305,11 +313,9 @@ func Flistxattr(fd int, dest []byte) (sz int, err error) {
|
||||||
destsiz := len(dest)
|
destsiz := len(dest)
|
||||||
|
|
||||||
s := 0
|
s := 0
|
||||||
var e error
|
|
||||||
for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
|
for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
|
||||||
stmp, e := ExtattrListFd(fd, nsid, uintptr(d), destsiz)
|
stmp, e := ExtattrListFd(fd, nsid, uintptr(d), destsiz)
|
||||||
if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
|
if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
|
||||||
e = nil
|
|
||||||
continue
|
continue
|
||||||
} else if e != nil {
|
} else if e != nil {
|
||||||
return s, e
|
return s, e
|
||||||
|
@ -323,7 +329,7 @@ func Flistxattr(fd int, dest []byte) (sz int, err error) {
|
||||||
d = initxattrdest(dest, s)
|
d = initxattrdest(dest, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, e
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Llistxattr(link string, dest []byte) (sz int, err error) {
|
func Llistxattr(link string, dest []byte) (sz int, err error) {
|
||||||
|
@ -331,11 +337,9 @@ func Llistxattr(link string, dest []byte) (sz int, err error) {
|
||||||
destsiz := len(dest)
|
destsiz := len(dest)
|
||||||
|
|
||||||
s := 0
|
s := 0
|
||||||
var e error
|
|
||||||
for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
|
for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
|
||||||
stmp, e := ExtattrListLink(link, nsid, uintptr(d), destsiz)
|
stmp, e := ExtattrListLink(link, nsid, uintptr(d), destsiz)
|
||||||
if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
|
if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
|
||||||
e = nil
|
|
||||||
continue
|
continue
|
||||||
} else if e != nil {
|
} else if e != nil {
|
||||||
return s, e
|
return s, e
|
||||||
|
@ -349,7 +353,7 @@ func Llistxattr(link string, dest []byte) (sz int, err error) {
|
||||||
d = initxattrdest(dest, s)
|
d = initxattrdest(dest, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, e
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
||||||
|
@ -391,6 +395,52 @@ func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||||
return &value, err
|
return &value, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Uname(uname *Utsname) error {
|
||||||
|
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
|
||||||
|
n := unsafe.Sizeof(uname.Sysname)
|
||||||
|
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
|
||||||
|
n = unsafe.Sizeof(uname.Nodename)
|
||||||
|
if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
|
||||||
|
n = unsafe.Sizeof(uname.Release)
|
||||||
|
if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_VERSION}
|
||||||
|
n = unsafe.Sizeof(uname.Version)
|
||||||
|
if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The version might have newlines or tabs in it, convert them to
|
||||||
|
// spaces.
|
||||||
|
for i, b := range uname.Version {
|
||||||
|
if b == '\n' || b == '\t' {
|
||||||
|
if i == len(uname.Version)-1 {
|
||||||
|
uname.Version[i] = 0
|
||||||
|
} else {
|
||||||
|
uname.Version[i] = ' '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_HW, HW_MACHINE}
|
||||||
|
n = unsafe.Sizeof(uname.Machine)
|
||||||
|
if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exposed directly
|
* Exposed directly
|
||||||
*/
|
*/
|
||||||
|
@ -434,6 +484,7 @@ func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||||
//sys Fstatfs(fd int, stat *Statfs_t) (err error)
|
//sys Fstatfs(fd int, stat *Statfs_t) (err error)
|
||||||
//sys Fsync(fd int) (err error)
|
//sys Fsync(fd int) (err error)
|
||||||
//sys Ftruncate(fd int, length int64) (err error)
|
//sys Ftruncate(fd int, length int64) (err error)
|
||||||
|
//sys Getdents(fd int, buf []byte) (n int, err error)
|
||||||
//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error)
|
//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error)
|
||||||
//sys Getdtablesize() (size int)
|
//sys Getdtablesize() (size int)
|
||||||
//sysnb Getegid() (egid int)
|
//sysnb Getegid() (egid int)
|
||||||
|
|
|
@ -16,6 +16,13 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SyscallNoError may be used instead of Syscall for syscalls that don't fail.
|
||||||
|
func SyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr)
|
||||||
|
|
||||||
|
// RawSyscallNoError may be used instead of RawSyscall for syscalls that don't
|
||||||
|
// fail.
|
||||||
|
func RawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrapped
|
* Wrapped
|
||||||
*/
|
*/
|
||||||
|
@ -468,6 +475,29 @@ func (sa *SockaddrHCI) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrHCI, nil
|
return unsafe.Pointer(&sa.raw), SizeofSockaddrHCI, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SockaddrL2 struct {
|
||||||
|
PSM uint16
|
||||||
|
CID uint16
|
||||||
|
Addr [6]uint8
|
||||||
|
AddrType uint8
|
||||||
|
raw RawSockaddrL2
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sa *SockaddrL2) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||||
|
sa.raw.Family = AF_BLUETOOTH
|
||||||
|
psm := (*[2]byte)(unsafe.Pointer(&sa.raw.Psm))
|
||||||
|
psm[0] = byte(sa.PSM)
|
||||||
|
psm[1] = byte(sa.PSM >> 8)
|
||||||
|
for i := 0; i < len(sa.Addr); i++ {
|
||||||
|
sa.raw.Bdaddr[i] = sa.Addr[len(sa.Addr)-1-i]
|
||||||
|
}
|
||||||
|
cid := (*[2]byte)(unsafe.Pointer(&sa.raw.Cid))
|
||||||
|
cid[0] = byte(sa.CID)
|
||||||
|
cid[1] = byte(sa.CID >> 8)
|
||||||
|
sa.raw.Bdaddr_type = sa.AddrType
|
||||||
|
return unsafe.Pointer(&sa.raw), SizeofSockaddrL2, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SockaddrCAN implements the Sockaddr interface for AF_CAN type sockets.
|
// SockaddrCAN implements the Sockaddr interface for AF_CAN type sockets.
|
||||||
// The RxID and TxID fields are used for transport protocol addressing in
|
// The RxID and TxID fields are used for transport protocol addressing in
|
||||||
// (CAN_TP16, CAN_TP20, CAN_MCNET, and CAN_ISOTP), they can be left with
|
// (CAN_TP16, CAN_TP20, CAN_MCNET, and CAN_ISOTP), they can be left with
|
||||||
|
@ -808,6 +838,24 @@ func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) {
|
||||||
return &value, err
|
return &value, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetsockoptString returns the string value of the socket option opt for the
|
||||||
|
// socket associated with fd at the given socket level.
|
||||||
|
func GetsockoptString(fd, level, opt int) (string, error) {
|
||||||
|
buf := make([]byte, 256)
|
||||||
|
vallen := _Socklen(len(buf))
|
||||||
|
err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
|
||||||
|
if err != nil {
|
||||||
|
if err == ERANGE {
|
||||||
|
buf = make([]byte, vallen)
|
||||||
|
err = getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(buf[:vallen-1]), nil
|
||||||
|
}
|
||||||
|
|
||||||
func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
|
func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
|
||||||
return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq))
|
return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq))
|
||||||
}
|
}
|
||||||
|
@ -1125,6 +1173,10 @@ func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) {
|
||||||
return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data)
|
return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PtracePokeUser(pid int, addr uintptr, data []byte) (count int, err error) {
|
||||||
|
return ptracePoke(PTRACE_POKEUSR, PTRACE_PEEKUSR, pid, addr, data)
|
||||||
|
}
|
||||||
|
|
||||||
func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) {
|
func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) {
|
||||||
return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
|
return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
|
||||||
}
|
}
|
||||||
|
@ -1168,22 +1220,6 @@ func ReadDirent(fd int, buf []byte) (n int, err error) {
|
||||||
return Getdents(fd, buf)
|
return Getdents(fd, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func direntIno(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntReclen(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntNamlen(buf []byte) (uint64, bool) {
|
|
||||||
reclen, ok := direntReclen(buf)
|
|
||||||
if !ok {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
|
|
||||||
}
|
|
||||||
|
|
||||||
//sys mount(source string, target string, fstype string, flags uintptr, data *byte) (err error)
|
//sys mount(source string, target string, fstype string, flags uintptr, data *byte) (err error)
|
||||||
|
|
||||||
func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
|
func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
|
||||||
|
@ -1289,6 +1325,7 @@ func Setgid(uid int) (err error) {
|
||||||
|
|
||||||
//sys Setpriority(which int, who int, prio int) (err error)
|
//sys Setpriority(which int, who int, prio int) (err error)
|
||||||
//sys Setxattr(path string, attr string, data []byte, flags int) (err error)
|
//sys Setxattr(path string, attr string, data []byte, flags int) (err error)
|
||||||
|
//sys Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error)
|
||||||
//sys Sync()
|
//sys Sync()
|
||||||
//sys Syncfs(fd int) (err error)
|
//sys Syncfs(fd int) (err error)
|
||||||
//sysnb Sysinfo(info *Sysinfo_t) (err error)
|
//sysnb Sysinfo(info *Sysinfo_t) (err error)
|
||||||
|
@ -1406,7 +1443,6 @@ func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) {
|
||||||
// Msgget
|
// Msgget
|
||||||
// Msgrcv
|
// Msgrcv
|
||||||
// Msgsnd
|
// Msgsnd
|
||||||
// Newfstatat
|
|
||||||
// Nfsservctl
|
// Nfsservctl
|
||||||
// Personality
|
// Personality
|
||||||
// Pselect6
|
// Pselect6
|
||||||
|
@ -1427,11 +1463,9 @@ func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) {
|
||||||
// RtSigtimedwait
|
// RtSigtimedwait
|
||||||
// SchedGetPriorityMax
|
// SchedGetPriorityMax
|
||||||
// SchedGetPriorityMin
|
// SchedGetPriorityMin
|
||||||
// SchedGetaffinity
|
|
||||||
// SchedGetparam
|
// SchedGetparam
|
||||||
// SchedGetscheduler
|
// SchedGetscheduler
|
||||||
// SchedRrGetInterval
|
// SchedRrGetInterval
|
||||||
// SchedSetaffinity
|
|
||||||
// SchedSetparam
|
// SchedSetparam
|
||||||
// SchedYield
|
// SchedYield
|
||||||
// Security
|
// Security
|
||||||
|
|
|
@ -54,6 +54,7 @@ func Pipe2(p []int, flags int) (err error) {
|
||||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64
|
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64
|
||||||
//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
|
//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
|
||||||
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
|
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
|
||||||
|
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
|
||||||
//sys Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64
|
//sys Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64
|
||||||
//sysnb Getegid() (egid int) = SYS_GETEGID32
|
//sysnb Getegid() (egid int) = SYS_GETEGID32
|
||||||
//sysnb Geteuid() (euid int) = SYS_GETEUID32
|
//sysnb Geteuid() (euid int) = SYS_GETEUID32
|
||||||
|
|
|
@ -11,6 +11,7 @@ package unix
|
||||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||||
//sys Fstat(fd int, stat *Stat_t) (err error)
|
//sys Fstat(fd int, stat *Stat_t) (err error)
|
||||||
|
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT
|
||||||
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
||||||
//sys Ftruncate(fd int, length int64) (err error)
|
//sys Ftruncate(fd int, length int64) (err error)
|
||||||
//sysnb Getegid() (egid int)
|
//sysnb Getegid() (egid int)
|
||||||
|
|
|
@ -77,6 +77,7 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
|
||||||
//sys Dup2(oldfd int, newfd int) (err error)
|
//sys Dup2(oldfd int, newfd int) (err error)
|
||||||
//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
|
//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
|
||||||
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
|
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
|
||||||
|
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
|
||||||
//sysnb Getegid() (egid int) = SYS_GETEGID32
|
//sysnb Getegid() (egid int) = SYS_GETEGID32
|
||||||
//sysnb Geteuid() (euid int) = SYS_GETEUID32
|
//sysnb Geteuid() (euid int) = SYS_GETEUID32
|
||||||
//sysnb Getgid() (gid int) = SYS_GETGID32
|
//sysnb Getgid() (gid int) = SYS_GETGID32
|
||||||
|
|
|
@ -10,6 +10,7 @@ package unix
|
||||||
//sys Dup2(oldfd int, newfd int) (err error)
|
//sys Dup2(oldfd int, newfd int) (err error)
|
||||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||||
|
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT
|
||||||
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
||||||
//sys Ftruncate(fd int, length int64) (err error)
|
//sys Ftruncate(fd int, length int64) (err error)
|
||||||
//sysnb Getegid() (egid int)
|
//sysnb Getegid() (egid int)
|
||||||
|
|
|
@ -65,6 +65,7 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
|
||||||
|
|
||||||
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
|
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
|
||||||
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
|
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
|
||||||
|
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
|
||||||
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
|
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
|
||||||
|
|
||||||
//sys Utime(path string, buf *Utimbuf) (err error)
|
//sys Utime(path string, buf *Utimbuf) (err error)
|
||||||
|
|
|
@ -11,6 +11,7 @@ package unix
|
||||||
//sys Dup2(oldfd int, newfd int) (err error)
|
//sys Dup2(oldfd int, newfd int) (err error)
|
||||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||||
//sys Fstat(fd int, stat *Stat_t) (err error)
|
//sys Fstat(fd int, stat *Stat_t) (err error)
|
||||||
|
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT
|
||||||
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
||||||
//sys Ftruncate(fd int, length int64) (err error)
|
//sys Ftruncate(fd int, length int64) (err error)
|
||||||
//sysnb Getegid() (egid int)
|
//sysnb Getegid() (egid int)
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||||
//sys Fstat(fd int, stat *Stat_t) (err error)
|
//sys Fstat(fd int, stat *Stat_t) (err error)
|
||||||
|
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT
|
||||||
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
||||||
//sys Ftruncate(fd int, length int64) (err error)
|
//sys Ftruncate(fd int, length int64) (err error)
|
||||||
//sysnb Getegid() (egid int)
|
//sysnb Getegid() (egid int)
|
||||||
|
|
|
@ -10,6 +10,7 @@ package unix
|
||||||
//sys Dup2(oldfd int, newfd int) (err error)
|
//sys Dup2(oldfd int, newfd int) (err error)
|
||||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||||
//sys Fstat(fd int, stat *Stat_t) (err error)
|
//sys Fstat(fd int, stat *Stat_t) (err error)
|
||||||
|
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
|
||||||
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
||||||
//sys Ftruncate(fd int, length int64) (err error)
|
//sys Ftruncate(fd int, length int64) (err error)
|
||||||
//sysnb Getegid() (egid int)
|
//sysnb Getegid() (egid int)
|
||||||
|
|
|
@ -55,7 +55,6 @@ func sysctlNodes(mib []_C_int) (nodes []Sysctlnode, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func nametomib(name string) (mib []_C_int, err error) {
|
func nametomib(name string) (mib []_C_int, err error) {
|
||||||
|
|
||||||
// Split name into components.
|
// Split name into components.
|
||||||
var parts []string
|
var parts []string
|
||||||
last := 0
|
last := 0
|
||||||
|
@ -93,18 +92,6 @@ func nametomib(name string) (mib []_C_int, err error) {
|
||||||
return mib, nil
|
return mib, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func direntIno(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntReclen(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntNamlen(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
|
||||||
}
|
|
||||||
|
|
||||||
//sysnb pipe() (fd1 int, fd2 int, err error)
|
//sysnb pipe() (fd1 int, fd2 int, err error)
|
||||||
func Pipe(p []int) (err error) {
|
func Pipe(p []int) (err error) {
|
||||||
if len(p) != 2 {
|
if len(p) != 2 {
|
||||||
|
@ -119,11 +106,118 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
||||||
return getdents(fd, buf)
|
return getdents(fd, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ImplementsGetwd = true
|
||||||
|
|
||||||
|
//sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD
|
||||||
|
|
||||||
|
func Getwd() (string, error) {
|
||||||
|
var buf [PathMax]byte
|
||||||
|
_, err := Getcwd(buf[0:])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
n := clen(buf[:])
|
||||||
|
if n < 1 {
|
||||||
|
return "", EINVAL
|
||||||
|
}
|
||||||
|
return string(buf[:n]), nil
|
||||||
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
|
func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
|
||||||
return -1, ENOSYS
|
return -1, ENOSYS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setattrlistTimes(path string, times []Timespec, flags int) error {
|
||||||
|
// used on Darwin for UtimesNano
|
||||||
|
return ENOSYS
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
||||||
|
|
||||||
|
// ioctl itself should not be exposed directly, but additional get/set
|
||||||
|
// functions for specific types are permissible.
|
||||||
|
|
||||||
|
// IoctlSetInt performs an ioctl operation which sets an integer value
|
||||||
|
// on fd, using the specified request number.
|
||||||
|
func IoctlSetInt(fd int, req uint, value int) error {
|
||||||
|
return ioctl(fd, req, uintptr(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
|
||||||
|
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlSetTermios(fd int, req uint, value *Termios) error {
|
||||||
|
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlGetInt performs an ioctl operation which gets an integer value
|
||||||
|
// from fd, using the specified request number.
|
||||||
|
func IoctlGetInt(fd int, req uint) (int, error) {
|
||||||
|
var value int
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
||||||
|
var value Winsize
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||||
|
var value Termios
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func Uname(uname *Utsname) error {
|
||||||
|
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
|
||||||
|
n := unsafe.Sizeof(uname.Sysname)
|
||||||
|
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
|
||||||
|
n = unsafe.Sizeof(uname.Nodename)
|
||||||
|
if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
|
||||||
|
n = unsafe.Sizeof(uname.Release)
|
||||||
|
if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_VERSION}
|
||||||
|
n = unsafe.Sizeof(uname.Version)
|
||||||
|
if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The version might have newlines or tabs in it, convert them to
|
||||||
|
// spaces.
|
||||||
|
for i, b := range uname.Version {
|
||||||
|
if b == '\n' || b == '\t' {
|
||||||
|
if i == len(uname.Version)-1 {
|
||||||
|
uname.Version[i] = 0
|
||||||
|
} else {
|
||||||
|
uname.Version[i] = ' '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_HW, HW_MACHINE}
|
||||||
|
n = unsafe.Sizeof(uname.Machine)
|
||||||
|
if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exposed directly
|
* Exposed directly
|
||||||
*/
|
*/
|
||||||
|
@ -384,7 +478,6 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||||
// getitimer
|
// getitimer
|
||||||
// getvfsstat
|
// getvfsstat
|
||||||
// getxattr
|
// getxattr
|
||||||
// ioctl
|
|
||||||
// ktrace
|
// ktrace
|
||||||
// lchflags
|
// lchflags
|
||||||
// lchmod
|
// lchmod
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build dragonfly freebsd netbsd openbsd
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
const ImplementsGetwd = false
|
|
||||||
|
|
||||||
func Getwd() (string, error) { return "", ENOTSUP }
|
|
|
@ -13,6 +13,7 @@
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sort"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
@ -32,39 +33,15 @@ type SockaddrDatalink struct {
|
||||||
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||||
|
|
||||||
func nametomib(name string) (mib []_C_int, err error) {
|
func nametomib(name string) (mib []_C_int, err error) {
|
||||||
|
i := sort.Search(len(sysctlMib), func(i int) bool {
|
||||||
// Perform lookup via a binary search
|
return sysctlMib[i].ctlname >= name
|
||||||
left := 0
|
})
|
||||||
right := len(sysctlMib) - 1
|
if i < len(sysctlMib) && sysctlMib[i].ctlname == name {
|
||||||
for {
|
return sysctlMib[i].ctloid, nil
|
||||||
idx := left + (right-left)/2
|
|
||||||
switch {
|
|
||||||
case name == sysctlMib[idx].ctlname:
|
|
||||||
return sysctlMib[idx].ctloid, nil
|
|
||||||
case name > sysctlMib[idx].ctlname:
|
|
||||||
left = idx + 1
|
|
||||||
default:
|
|
||||||
right = idx - 1
|
|
||||||
}
|
|
||||||
if left > right {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil, EINVAL
|
return nil, EINVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
func direntIno(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntReclen(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntNamlen(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
|
||||||
}
|
|
||||||
|
|
||||||
//sysnb pipe(p *[2]_C_int) (err error)
|
//sysnb pipe(p *[2]_C_int) (err error)
|
||||||
func Pipe(p []int) (err error) {
|
func Pipe(p []int) (err error) {
|
||||||
if len(p) != 2 {
|
if len(p) != 2 {
|
||||||
|
@ -82,6 +59,23 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
||||||
return getdents(fd, buf)
|
return getdents(fd, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ImplementsGetwd = true
|
||||||
|
|
||||||
|
//sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD
|
||||||
|
|
||||||
|
func Getwd() (string, error) {
|
||||||
|
var buf [PathMax]byte
|
||||||
|
_, err := Getcwd(buf[0:])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
n := clen(buf[:])
|
||||||
|
if n < 1 {
|
||||||
|
return "", EINVAL
|
||||||
|
}
|
||||||
|
return string(buf[:n]), nil
|
||||||
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
|
func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
|
||||||
return -1, ENOSYS
|
return -1, ENOSYS
|
||||||
|
@ -102,6 +96,96 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setattrlistTimes(path string, times []Timespec, flags int) error {
|
||||||
|
// used on Darwin for UtimesNano
|
||||||
|
return ENOSYS
|
||||||
|
}
|
||||||
|
|
||||||
|
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
||||||
|
|
||||||
|
// ioctl itself should not be exposed directly, but additional get/set
|
||||||
|
// functions for specific types are permissible.
|
||||||
|
|
||||||
|
// IoctlSetInt performs an ioctl operation which sets an integer value
|
||||||
|
// on fd, using the specified request number.
|
||||||
|
func IoctlSetInt(fd int, req uint, value int) error {
|
||||||
|
return ioctl(fd, req, uintptr(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
|
||||||
|
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlSetTermios(fd int, req uint, value *Termios) error {
|
||||||
|
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlGetInt performs an ioctl operation which gets an integer value
|
||||||
|
// from fd, using the specified request number.
|
||||||
|
func IoctlGetInt(fd int, req uint) (int, error) {
|
||||||
|
var value int
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
||||||
|
var value Winsize
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||||
|
var value Termios
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func Uname(uname *Utsname) error {
|
||||||
|
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
|
||||||
|
n := unsafe.Sizeof(uname.Sysname)
|
||||||
|
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
|
||||||
|
n = unsafe.Sizeof(uname.Nodename)
|
||||||
|
if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
|
||||||
|
n = unsafe.Sizeof(uname.Release)
|
||||||
|
if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_KERN, KERN_VERSION}
|
||||||
|
n = unsafe.Sizeof(uname.Version)
|
||||||
|
if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The version might have newlines or tabs in it, convert them to
|
||||||
|
// spaces.
|
||||||
|
for i, b := range uname.Version {
|
||||||
|
if b == '\n' || b == '\t' {
|
||||||
|
if i == len(uname.Version)-1 {
|
||||||
|
uname.Version[i] = 0
|
||||||
|
} else {
|
||||||
|
uname.Version[i] = ' '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = []_C_int{CTL_HW, HW_MACHINE}
|
||||||
|
n = unsafe.Sizeof(uname.Machine)
|
||||||
|
if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exposed directly
|
* Exposed directly
|
||||||
*/
|
*/
|
||||||
|
@ -222,7 +306,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
|
||||||
// getresuid
|
// getresuid
|
||||||
// getrtable
|
// getrtable
|
||||||
// getthrid
|
// getthrid
|
||||||
// ioctl
|
|
||||||
// ktrace
|
// ktrace
|
||||||
// lfs_bmapv
|
// lfs_bmapv
|
||||||
// lfs_markv
|
// lfs_markv
|
||||||
|
|
|
@ -34,31 +34,6 @@ type SockaddrDatalink struct {
|
||||||
raw RawSockaddrDatalink
|
raw RawSockaddrDatalink
|
||||||
}
|
}
|
||||||
|
|
||||||
func clen(n []byte) int {
|
|
||||||
for i := 0; i < len(n); i++ {
|
|
||||||
if n[i] == 0 {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return len(n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntIno(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntReclen(buf []byte) (uint64, bool) {
|
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
|
||||||
}
|
|
||||||
|
|
||||||
func direntNamlen(buf []byte) (uint64, bool) {
|
|
||||||
reclen, ok := direntReclen(buf)
|
|
||||||
if !ok {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
|
|
||||||
}
|
|
||||||
|
|
||||||
//sysnb pipe(p *[2]_C_int) (n int, err error)
|
//sysnb pipe(p *[2]_C_int) (n int, err error)
|
||||||
|
|
||||||
func Pipe(p []int) (err error) {
|
func Pipe(p []int) (err error) {
|
||||||
|
@ -139,6 +114,18 @@ func Getsockname(fd int) (sa Sockaddr, err error) {
|
||||||
return anyToSockaddr(&rsa)
|
return anyToSockaddr(&rsa)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetsockoptString returns the string value of the socket option opt for the
|
||||||
|
// socket associated with fd at the given socket level.
|
||||||
|
func GetsockoptString(fd, level, opt int) (string, error) {
|
||||||
|
buf := make([]byte, 256)
|
||||||
|
vallen := _Socklen(len(buf))
|
||||||
|
err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(buf[:vallen-1]), nil
|
||||||
|
}
|
||||||
|
|
||||||
const ImplementsGetwd = true
|
const ImplementsGetwd = true
|
||||||
|
|
||||||
//sys Getcwd(buf []byte) (n int, err error)
|
//sys Getcwd(buf []byte) (n int, err error)
|
||||||
|
@ -655,6 +642,7 @@ func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||||
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
|
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
|
||||||
//sys Rmdir(path string) (err error)
|
//sys Rmdir(path string) (err error)
|
||||||
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
|
//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
|
||||||
|
//sys Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error)
|
||||||
//sysnb Setegid(egid int) (err error)
|
//sysnb Setegid(egid int) (err error)
|
||||||
//sysnb Seteuid(euid int) (err error)
|
//sysnb Seteuid(euid int) (err error)
|
||||||
//sysnb Setgid(gid int) (err error)
|
//sysnb Setgid(gid int) (err error)
|
||||||
|
|
|
@ -50,6 +50,17 @@ func errnoErr(e syscall.Errno) error {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clen returns the index of the first NULL byte in n or len(n) if n contains no
|
||||||
|
// NULL byte or len(n) if n contains no NULL byte
|
||||||
|
func clen(n []byte) int {
|
||||||
|
for i := 0; i < len(n); i++ {
|
||||||
|
if n[i] == 0 {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len(n)
|
||||||
|
}
|
||||||
|
|
||||||
// Mmap manager, for use by operating system-specific implementations.
|
// Mmap manager, for use by operating system-specific implementations.
|
||||||
|
|
||||||
type mmapper struct {
|
type mmapper struct {
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
// TimespecToNsec converts a Timespec value into a number of
|
// TimespecToNsec converts a Timespec value into a number of
|
||||||
// nanoseconds since the Unix epoch.
|
// nanoseconds since the Unix epoch.
|
||||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||||
|
@ -22,6 +24,24 @@ func NsecToTimespec(nsec int64) Timespec {
|
||||||
return setTimespec(sec, nsec)
|
return setTimespec(sec, nsec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TimeToTimespec converts t into a Timespec.
|
||||||
|
// On some 32-bit systems the range of valid Timespec values are smaller
|
||||||
|
// than that of time.Time values. So if t is out of the valid range of
|
||||||
|
// Timespec, it returns a zero Timespec and ERANGE.
|
||||||
|
func TimeToTimespec(t time.Time) (Timespec, error) {
|
||||||
|
sec := t.Unix()
|
||||||
|
nsec := int64(t.Nanosecond())
|
||||||
|
ts := setTimespec(sec, nsec)
|
||||||
|
|
||||||
|
// Currently all targets have either int32 or int64 for Timespec.Sec.
|
||||||
|
// If there were a new target with floating point type for it, we have
|
||||||
|
// to consider the rounding error.
|
||||||
|
if int64(ts.Sec) != sec {
|
||||||
|
return Timespec{}, ERANGE
|
||||||
|
}
|
||||||
|
return ts, nil
|
||||||
|
}
|
||||||
|
|
||||||
// TimevalToNsec converts a Timeval value into a number of nanoseconds
|
// TimevalToNsec converts a Timeval value into a number of nanoseconds
|
||||||
// since the Unix epoch.
|
// since the Unix epoch.
|
||||||
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
||||||
|
|
|
@ -49,6 +49,86 @@ const (
|
||||||
AF_UNSPEC = 0x0
|
AF_UNSPEC = 0x0
|
||||||
AF_UTUN = 0x26
|
AF_UTUN = 0x26
|
||||||
ALTWERASE = 0x200
|
ALTWERASE = 0x200
|
||||||
|
ATTR_BIT_MAP_COUNT = 0x5
|
||||||
|
ATTR_CMN_ACCESSMASK = 0x20000
|
||||||
|
ATTR_CMN_ACCTIME = 0x1000
|
||||||
|
ATTR_CMN_ADDEDTIME = 0x10000000
|
||||||
|
ATTR_CMN_BKUPTIME = 0x2000
|
||||||
|
ATTR_CMN_CHGTIME = 0x800
|
||||||
|
ATTR_CMN_CRTIME = 0x200
|
||||||
|
ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000
|
||||||
|
ATTR_CMN_DEVID = 0x2
|
||||||
|
ATTR_CMN_DOCUMENT_ID = 0x100000
|
||||||
|
ATTR_CMN_ERROR = 0x20000000
|
||||||
|
ATTR_CMN_EXTENDED_SECURITY = 0x400000
|
||||||
|
ATTR_CMN_FILEID = 0x2000000
|
||||||
|
ATTR_CMN_FLAGS = 0x40000
|
||||||
|
ATTR_CMN_FNDRINFO = 0x4000
|
||||||
|
ATTR_CMN_FSID = 0x4
|
||||||
|
ATTR_CMN_FULLPATH = 0x8000000
|
||||||
|
ATTR_CMN_GEN_COUNT = 0x80000
|
||||||
|
ATTR_CMN_GRPID = 0x10000
|
||||||
|
ATTR_CMN_GRPUUID = 0x1000000
|
||||||
|
ATTR_CMN_MODTIME = 0x400
|
||||||
|
ATTR_CMN_NAME = 0x1
|
||||||
|
ATTR_CMN_NAMEDATTRCOUNT = 0x80000
|
||||||
|
ATTR_CMN_NAMEDATTRLIST = 0x100000
|
||||||
|
ATTR_CMN_OBJID = 0x20
|
||||||
|
ATTR_CMN_OBJPERMANENTID = 0x40
|
||||||
|
ATTR_CMN_OBJTAG = 0x10
|
||||||
|
ATTR_CMN_OBJTYPE = 0x8
|
||||||
|
ATTR_CMN_OWNERID = 0x8000
|
||||||
|
ATTR_CMN_PARENTID = 0x4000000
|
||||||
|
ATTR_CMN_PAROBJID = 0x80
|
||||||
|
ATTR_CMN_RETURNED_ATTRS = 0x80000000
|
||||||
|
ATTR_CMN_SCRIPT = 0x100
|
||||||
|
ATTR_CMN_SETMASK = 0x41c7ff00
|
||||||
|
ATTR_CMN_USERACCESS = 0x200000
|
||||||
|
ATTR_CMN_UUID = 0x800000
|
||||||
|
ATTR_CMN_VALIDMASK = 0xffffffff
|
||||||
|
ATTR_CMN_VOLSETMASK = 0x6700
|
||||||
|
ATTR_FILE_ALLOCSIZE = 0x4
|
||||||
|
ATTR_FILE_CLUMPSIZE = 0x10
|
||||||
|
ATTR_FILE_DATAALLOCSIZE = 0x400
|
||||||
|
ATTR_FILE_DATAEXTENTS = 0x800
|
||||||
|
ATTR_FILE_DATALENGTH = 0x200
|
||||||
|
ATTR_FILE_DEVTYPE = 0x20
|
||||||
|
ATTR_FILE_FILETYPE = 0x40
|
||||||
|
ATTR_FILE_FORKCOUNT = 0x80
|
||||||
|
ATTR_FILE_FORKLIST = 0x100
|
||||||
|
ATTR_FILE_IOBLOCKSIZE = 0x8
|
||||||
|
ATTR_FILE_LINKCOUNT = 0x1
|
||||||
|
ATTR_FILE_RSRCALLOCSIZE = 0x2000
|
||||||
|
ATTR_FILE_RSRCEXTENTS = 0x4000
|
||||||
|
ATTR_FILE_RSRCLENGTH = 0x1000
|
||||||
|
ATTR_FILE_SETMASK = 0x20
|
||||||
|
ATTR_FILE_TOTALSIZE = 0x2
|
||||||
|
ATTR_FILE_VALIDMASK = 0x37ff
|
||||||
|
ATTR_VOL_ALLOCATIONCLUMP = 0x40
|
||||||
|
ATTR_VOL_ATTRIBUTES = 0x40000000
|
||||||
|
ATTR_VOL_CAPABILITIES = 0x20000
|
||||||
|
ATTR_VOL_DIRCOUNT = 0x400
|
||||||
|
ATTR_VOL_ENCODINGSUSED = 0x10000
|
||||||
|
ATTR_VOL_FILECOUNT = 0x200
|
||||||
|
ATTR_VOL_FSTYPE = 0x1
|
||||||
|
ATTR_VOL_INFO = 0x80000000
|
||||||
|
ATTR_VOL_IOBLOCKSIZE = 0x80
|
||||||
|
ATTR_VOL_MAXOBJCOUNT = 0x800
|
||||||
|
ATTR_VOL_MINALLOCATION = 0x20
|
||||||
|
ATTR_VOL_MOUNTEDDEVICE = 0x8000
|
||||||
|
ATTR_VOL_MOUNTFLAGS = 0x4000
|
||||||
|
ATTR_VOL_MOUNTPOINT = 0x1000
|
||||||
|
ATTR_VOL_NAME = 0x2000
|
||||||
|
ATTR_VOL_OBJCOUNT = 0x100
|
||||||
|
ATTR_VOL_QUOTA_SIZE = 0x10000000
|
||||||
|
ATTR_VOL_RESERVED_SIZE = 0x20000000
|
||||||
|
ATTR_VOL_SETMASK = 0x80002000
|
||||||
|
ATTR_VOL_SIGNATURE = 0x2
|
||||||
|
ATTR_VOL_SIZE = 0x4
|
||||||
|
ATTR_VOL_SPACEAVAIL = 0x10
|
||||||
|
ATTR_VOL_SPACEFREE = 0x8
|
||||||
|
ATTR_VOL_UUID = 0x40000
|
||||||
|
ATTR_VOL_VALIDMASK = 0xf007ffff
|
||||||
B0 = 0x0
|
B0 = 0x0
|
||||||
B110 = 0x6e
|
B110 = 0x6e
|
||||||
B115200 = 0x1c200
|
B115200 = 0x1c200
|
||||||
|
@ -169,6 +249,8 @@ const (
|
||||||
CSTOP = 0x13
|
CSTOP = 0x13
|
||||||
CSTOPB = 0x400
|
CSTOPB = 0x400
|
||||||
CSUSP = 0x1a
|
CSUSP = 0x1a
|
||||||
|
CTL_HW = 0x6
|
||||||
|
CTL_KERN = 0x1
|
||||||
CTL_MAXNAME = 0xc
|
CTL_MAXNAME = 0xc
|
||||||
CTL_NET = 0x4
|
CTL_NET = 0x4
|
||||||
DLT_A429 = 0xb8
|
DLT_A429 = 0xb8
|
||||||
|
@ -390,6 +472,11 @@ const (
|
||||||
FF1 = 0x4000
|
FF1 = 0x4000
|
||||||
FFDLY = 0x4000
|
FFDLY = 0x4000
|
||||||
FLUSHO = 0x800000
|
FLUSHO = 0x800000
|
||||||
|
FSOPT_ATTR_CMN_EXTENDED = 0x20
|
||||||
|
FSOPT_NOFOLLOW = 0x1
|
||||||
|
FSOPT_NOINMEMUPDATE = 0x2
|
||||||
|
FSOPT_PACK_INVAL_ATTRS = 0x8
|
||||||
|
FSOPT_REPORT_FULLSIZE = 0x4
|
||||||
F_ADDFILESIGS = 0x3d
|
F_ADDFILESIGS = 0x3d
|
||||||
F_ADDFILESIGS_FOR_DYLD_SIM = 0x53
|
F_ADDFILESIGS_FOR_DYLD_SIM = 0x53
|
||||||
F_ADDFILESIGS_RETURN = 0x61
|
F_ADDFILESIGS_RETURN = 0x61
|
||||||
|
@ -425,6 +512,7 @@ const (
|
||||||
F_PATHPKG_CHECK = 0x34
|
F_PATHPKG_CHECK = 0x34
|
||||||
F_PEOFPOSMODE = 0x3
|
F_PEOFPOSMODE = 0x3
|
||||||
F_PREALLOCATE = 0x2a
|
F_PREALLOCATE = 0x2a
|
||||||
|
F_PUNCHHOLE = 0x63
|
||||||
F_RDADVISE = 0x2c
|
F_RDADVISE = 0x2c
|
||||||
F_RDAHEAD = 0x2d
|
F_RDAHEAD = 0x2d
|
||||||
F_RDLCK = 0x1
|
F_RDLCK = 0x1
|
||||||
|
@ -441,10 +529,12 @@ const (
|
||||||
F_SINGLE_WRITER = 0x4c
|
F_SINGLE_WRITER = 0x4c
|
||||||
F_THAW_FS = 0x36
|
F_THAW_FS = 0x36
|
||||||
F_TRANSCODEKEY = 0x4b
|
F_TRANSCODEKEY = 0x4b
|
||||||
|
F_TRIM_ACTIVE_FILE = 0x64
|
||||||
F_UNLCK = 0x2
|
F_UNLCK = 0x2
|
||||||
F_VOLPOSMODE = 0x4
|
F_VOLPOSMODE = 0x4
|
||||||
F_WRLCK = 0x3
|
F_WRLCK = 0x3
|
||||||
HUPCL = 0x4000
|
HUPCL = 0x4000
|
||||||
|
HW_MACHINE = 0x1
|
||||||
ICANON = 0x100
|
ICANON = 0x100
|
||||||
ICMP6_FILTER = 0x12
|
ICMP6_FILTER = 0x12
|
||||||
ICRNL = 0x100
|
ICRNL = 0x100
|
||||||
|
@ -681,6 +771,7 @@ const (
|
||||||
IPV6_FAITH = 0x1d
|
IPV6_FAITH = 0x1d
|
||||||
IPV6_FLOWINFO_MASK = 0xffffff0f
|
IPV6_FLOWINFO_MASK = 0xffffff0f
|
||||||
IPV6_FLOWLABEL_MASK = 0xffff0f00
|
IPV6_FLOWLABEL_MASK = 0xffff0f00
|
||||||
|
IPV6_FLOW_ECN_MASK = 0x300
|
||||||
IPV6_FRAGTTL = 0x3c
|
IPV6_FRAGTTL = 0x3c
|
||||||
IPV6_FW_ADD = 0x1e
|
IPV6_FW_ADD = 0x1e
|
||||||
IPV6_FW_DEL = 0x1f
|
IPV6_FW_DEL = 0x1f
|
||||||
|
@ -771,6 +862,7 @@ const (
|
||||||
IP_RECVOPTS = 0x5
|
IP_RECVOPTS = 0x5
|
||||||
IP_RECVPKTINFO = 0x1a
|
IP_RECVPKTINFO = 0x1a
|
||||||
IP_RECVRETOPTS = 0x6
|
IP_RECVRETOPTS = 0x6
|
||||||
|
IP_RECVTOS = 0x1b
|
||||||
IP_RECVTTL = 0x18
|
IP_RECVTTL = 0x18
|
||||||
IP_RETOPTS = 0x8
|
IP_RETOPTS = 0x8
|
||||||
IP_RF = 0x8000
|
IP_RF = 0x8000
|
||||||
|
@ -789,6 +881,10 @@ const (
|
||||||
IXANY = 0x800
|
IXANY = 0x800
|
||||||
IXOFF = 0x400
|
IXOFF = 0x400
|
||||||
IXON = 0x200
|
IXON = 0x200
|
||||||
|
KERN_HOSTNAME = 0xa
|
||||||
|
KERN_OSRELEASE = 0x2
|
||||||
|
KERN_OSTYPE = 0x1
|
||||||
|
KERN_VERSION = 0x4
|
||||||
LOCK_EX = 0x2
|
LOCK_EX = 0x2
|
||||||
LOCK_NB = 0x4
|
LOCK_NB = 0x4
|
||||||
LOCK_SH = 0x1
|
LOCK_SH = 0x1
|
||||||
|
|
|
@ -49,6 +49,86 @@ const (
|
||||||
AF_UNSPEC = 0x0
|
AF_UNSPEC = 0x0
|
||||||
AF_UTUN = 0x26
|
AF_UTUN = 0x26
|
||||||
ALTWERASE = 0x200
|
ALTWERASE = 0x200
|
||||||
|
ATTR_BIT_MAP_COUNT = 0x5
|
||||||
|
ATTR_CMN_ACCESSMASK = 0x20000
|
||||||
|
ATTR_CMN_ACCTIME = 0x1000
|
||||||
|
ATTR_CMN_ADDEDTIME = 0x10000000
|
||||||
|
ATTR_CMN_BKUPTIME = 0x2000
|
||||||
|
ATTR_CMN_CHGTIME = 0x800
|
||||||
|
ATTR_CMN_CRTIME = 0x200
|
||||||
|
ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000
|
||||||
|
ATTR_CMN_DEVID = 0x2
|
||||||
|
ATTR_CMN_DOCUMENT_ID = 0x100000
|
||||||
|
ATTR_CMN_ERROR = 0x20000000
|
||||||
|
ATTR_CMN_EXTENDED_SECURITY = 0x400000
|
||||||
|
ATTR_CMN_FILEID = 0x2000000
|
||||||
|
ATTR_CMN_FLAGS = 0x40000
|
||||||
|
ATTR_CMN_FNDRINFO = 0x4000
|
||||||
|
ATTR_CMN_FSID = 0x4
|
||||||
|
ATTR_CMN_FULLPATH = 0x8000000
|
||||||
|
ATTR_CMN_GEN_COUNT = 0x80000
|
||||||
|
ATTR_CMN_GRPID = 0x10000
|
||||||
|
ATTR_CMN_GRPUUID = 0x1000000
|
||||||
|
ATTR_CMN_MODTIME = 0x400
|
||||||
|
ATTR_CMN_NAME = 0x1
|
||||||
|
ATTR_CMN_NAMEDATTRCOUNT = 0x80000
|
||||||
|
ATTR_CMN_NAMEDATTRLIST = 0x100000
|
||||||
|
ATTR_CMN_OBJID = 0x20
|
||||||
|
ATTR_CMN_OBJPERMANENTID = 0x40
|
||||||
|
ATTR_CMN_OBJTAG = 0x10
|
||||||
|
ATTR_CMN_OBJTYPE = 0x8
|
||||||
|
ATTR_CMN_OWNERID = 0x8000
|
||||||
|
ATTR_CMN_PARENTID = 0x4000000
|
||||||
|
ATTR_CMN_PAROBJID = 0x80
|
||||||
|
ATTR_CMN_RETURNED_ATTRS = 0x80000000
|
||||||
|
ATTR_CMN_SCRIPT = 0x100
|
||||||
|
ATTR_CMN_SETMASK = 0x41c7ff00
|
||||||
|
ATTR_CMN_USERACCESS = 0x200000
|
||||||
|
ATTR_CMN_UUID = 0x800000
|
||||||
|
ATTR_CMN_VALIDMASK = 0xffffffff
|
||||||
|
ATTR_CMN_VOLSETMASK = 0x6700
|
||||||
|
ATTR_FILE_ALLOCSIZE = 0x4
|
||||||
|
ATTR_FILE_CLUMPSIZE = 0x10
|
||||||
|
ATTR_FILE_DATAALLOCSIZE = 0x400
|
||||||
|
ATTR_FILE_DATAEXTENTS = 0x800
|
||||||
|
ATTR_FILE_DATALENGTH = 0x200
|
||||||
|
ATTR_FILE_DEVTYPE = 0x20
|
||||||
|
ATTR_FILE_FILETYPE = 0x40
|
||||||
|
ATTR_FILE_FORKCOUNT = 0x80
|
||||||
|
ATTR_FILE_FORKLIST = 0x100
|
||||||
|
ATTR_FILE_IOBLOCKSIZE = 0x8
|
||||||
|
ATTR_FILE_LINKCOUNT = 0x1
|
||||||
|
ATTR_FILE_RSRCALLOCSIZE = 0x2000
|
||||||
|
ATTR_FILE_RSRCEXTENTS = 0x4000
|
||||||
|
ATTR_FILE_RSRCLENGTH = 0x1000
|
||||||
|
ATTR_FILE_SETMASK = 0x20
|
||||||
|
ATTR_FILE_TOTALSIZE = 0x2
|
||||||
|
ATTR_FILE_VALIDMASK = 0x37ff
|
||||||
|
ATTR_VOL_ALLOCATIONCLUMP = 0x40
|
||||||
|
ATTR_VOL_ATTRIBUTES = 0x40000000
|
||||||
|
ATTR_VOL_CAPABILITIES = 0x20000
|
||||||
|
ATTR_VOL_DIRCOUNT = 0x400
|
||||||
|
ATTR_VOL_ENCODINGSUSED = 0x10000
|
||||||
|
ATTR_VOL_FILECOUNT = 0x200
|
||||||
|
ATTR_VOL_FSTYPE = 0x1
|
||||||
|
ATTR_VOL_INFO = 0x80000000
|
||||||
|
ATTR_VOL_IOBLOCKSIZE = 0x80
|
||||||
|
ATTR_VOL_MAXOBJCOUNT = 0x800
|
||||||
|
ATTR_VOL_MINALLOCATION = 0x20
|
||||||
|
ATTR_VOL_MOUNTEDDEVICE = 0x8000
|
||||||
|
ATTR_VOL_MOUNTFLAGS = 0x4000
|
||||||
|
ATTR_VOL_MOUNTPOINT = 0x1000
|
||||||
|
ATTR_VOL_NAME = 0x2000
|
||||||
|
ATTR_VOL_OBJCOUNT = 0x100
|
||||||
|
ATTR_VOL_QUOTA_SIZE = 0x10000000
|
||||||
|
ATTR_VOL_RESERVED_SIZE = 0x20000000
|
||||||
|
ATTR_VOL_SETMASK = 0x80002000
|
||||||
|
ATTR_VOL_SIGNATURE = 0x2
|
||||||
|
ATTR_VOL_SIZE = 0x4
|
||||||
|
ATTR_VOL_SPACEAVAIL = 0x10
|
||||||
|
ATTR_VOL_SPACEFREE = 0x8
|
||||||
|
ATTR_VOL_UUID = 0x40000
|
||||||
|
ATTR_VOL_VALIDMASK = 0xf007ffff
|
||||||
B0 = 0x0
|
B0 = 0x0
|
||||||
B110 = 0x6e
|
B110 = 0x6e
|
||||||
B115200 = 0x1c200
|
B115200 = 0x1c200
|
||||||
|
@ -169,6 +249,8 @@ const (
|
||||||
CSTOP = 0x13
|
CSTOP = 0x13
|
||||||
CSTOPB = 0x400
|
CSTOPB = 0x400
|
||||||
CSUSP = 0x1a
|
CSUSP = 0x1a
|
||||||
|
CTL_HW = 0x6
|
||||||
|
CTL_KERN = 0x1
|
||||||
CTL_MAXNAME = 0xc
|
CTL_MAXNAME = 0xc
|
||||||
CTL_NET = 0x4
|
CTL_NET = 0x4
|
||||||
DLT_A429 = 0xb8
|
DLT_A429 = 0xb8
|
||||||
|
@ -390,6 +472,11 @@ const (
|
||||||
FF1 = 0x4000
|
FF1 = 0x4000
|
||||||
FFDLY = 0x4000
|
FFDLY = 0x4000
|
||||||
FLUSHO = 0x800000
|
FLUSHO = 0x800000
|
||||||
|
FSOPT_ATTR_CMN_EXTENDED = 0x20
|
||||||
|
FSOPT_NOFOLLOW = 0x1
|
||||||
|
FSOPT_NOINMEMUPDATE = 0x2
|
||||||
|
FSOPT_PACK_INVAL_ATTRS = 0x8
|
||||||
|
FSOPT_REPORT_FULLSIZE = 0x4
|
||||||
F_ADDFILESIGS = 0x3d
|
F_ADDFILESIGS = 0x3d
|
||||||
F_ADDFILESIGS_FOR_DYLD_SIM = 0x53
|
F_ADDFILESIGS_FOR_DYLD_SIM = 0x53
|
||||||
F_ADDFILESIGS_RETURN = 0x61
|
F_ADDFILESIGS_RETURN = 0x61
|
||||||
|
@ -425,6 +512,7 @@ const (
|
||||||
F_PATHPKG_CHECK = 0x34
|
F_PATHPKG_CHECK = 0x34
|
||||||
F_PEOFPOSMODE = 0x3
|
F_PEOFPOSMODE = 0x3
|
||||||
F_PREALLOCATE = 0x2a
|
F_PREALLOCATE = 0x2a
|
||||||
|
F_PUNCHHOLE = 0x63
|
||||||
F_RDADVISE = 0x2c
|
F_RDADVISE = 0x2c
|
||||||
F_RDAHEAD = 0x2d
|
F_RDAHEAD = 0x2d
|
||||||
F_RDLCK = 0x1
|
F_RDLCK = 0x1
|
||||||
|
@ -441,10 +529,12 @@ const (
|
||||||
F_SINGLE_WRITER = 0x4c
|
F_SINGLE_WRITER = 0x4c
|
||||||
F_THAW_FS = 0x36
|
F_THAW_FS = 0x36
|
||||||
F_TRANSCODEKEY = 0x4b
|
F_TRANSCODEKEY = 0x4b
|
||||||
|
F_TRIM_ACTIVE_FILE = 0x64
|
||||||
F_UNLCK = 0x2
|
F_UNLCK = 0x2
|
||||||
F_VOLPOSMODE = 0x4
|
F_VOLPOSMODE = 0x4
|
||||||
F_WRLCK = 0x3
|
F_WRLCK = 0x3
|
||||||
HUPCL = 0x4000
|
HUPCL = 0x4000
|
||||||
|
HW_MACHINE = 0x1
|
||||||
ICANON = 0x100
|
ICANON = 0x100
|
||||||
ICMP6_FILTER = 0x12
|
ICMP6_FILTER = 0x12
|
||||||
ICRNL = 0x100
|
ICRNL = 0x100
|
||||||
|
@ -681,6 +771,7 @@ const (
|
||||||
IPV6_FAITH = 0x1d
|
IPV6_FAITH = 0x1d
|
||||||
IPV6_FLOWINFO_MASK = 0xffffff0f
|
IPV6_FLOWINFO_MASK = 0xffffff0f
|
||||||
IPV6_FLOWLABEL_MASK = 0xffff0f00
|
IPV6_FLOWLABEL_MASK = 0xffff0f00
|
||||||
|
IPV6_FLOW_ECN_MASK = 0x300
|
||||||
IPV6_FRAGTTL = 0x3c
|
IPV6_FRAGTTL = 0x3c
|
||||||
IPV6_FW_ADD = 0x1e
|
IPV6_FW_ADD = 0x1e
|
||||||
IPV6_FW_DEL = 0x1f
|
IPV6_FW_DEL = 0x1f
|
||||||
|
@ -771,6 +862,7 @@ const (
|
||||||
IP_RECVOPTS = 0x5
|
IP_RECVOPTS = 0x5
|
||||||
IP_RECVPKTINFO = 0x1a
|
IP_RECVPKTINFO = 0x1a
|
||||||
IP_RECVRETOPTS = 0x6
|
IP_RECVRETOPTS = 0x6
|
||||||
|
IP_RECVTOS = 0x1b
|
||||||
IP_RECVTTL = 0x18
|
IP_RECVTTL = 0x18
|
||||||
IP_RETOPTS = 0x8
|
IP_RETOPTS = 0x8
|
||||||
IP_RF = 0x8000
|
IP_RF = 0x8000
|
||||||
|
@ -789,6 +881,10 @@ const (
|
||||||
IXANY = 0x800
|
IXANY = 0x800
|
||||||
IXOFF = 0x400
|
IXOFF = 0x400
|
||||||
IXON = 0x200
|
IXON = 0x200
|
||||||
|
KERN_HOSTNAME = 0xa
|
||||||
|
KERN_OSRELEASE = 0x2
|
||||||
|
KERN_OSTYPE = 0x1
|
||||||
|
KERN_VERSION = 0x4
|
||||||
LOCK_EX = 0x2
|
LOCK_EX = 0x2
|
||||||
LOCK_NB = 0x4
|
LOCK_NB = 0x4
|
||||||
LOCK_SH = 0x1
|
LOCK_SH = 0x1
|
||||||
|
|
|
@ -49,6 +49,86 @@ const (
|
||||||
AF_UNSPEC = 0x0
|
AF_UNSPEC = 0x0
|
||||||
AF_UTUN = 0x26
|
AF_UTUN = 0x26
|
||||||
ALTWERASE = 0x200
|
ALTWERASE = 0x200
|
||||||
|
ATTR_BIT_MAP_COUNT = 0x5
|
||||||
|
ATTR_CMN_ACCESSMASK = 0x20000
|
||||||
|
ATTR_CMN_ACCTIME = 0x1000
|
||||||
|
ATTR_CMN_ADDEDTIME = 0x10000000
|
||||||
|
ATTR_CMN_BKUPTIME = 0x2000
|
||||||
|
ATTR_CMN_CHGTIME = 0x800
|
||||||
|
ATTR_CMN_CRTIME = 0x200
|
||||||
|
ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000
|
||||||
|
ATTR_CMN_DEVID = 0x2
|
||||||
|
ATTR_CMN_DOCUMENT_ID = 0x100000
|
||||||
|
ATTR_CMN_ERROR = 0x20000000
|
||||||
|
ATTR_CMN_EXTENDED_SECURITY = 0x400000
|
||||||
|
ATTR_CMN_FILEID = 0x2000000
|
||||||
|
ATTR_CMN_FLAGS = 0x40000
|
||||||
|
ATTR_CMN_FNDRINFO = 0x4000
|
||||||
|
ATTR_CMN_FSID = 0x4
|
||||||
|
ATTR_CMN_FULLPATH = 0x8000000
|
||||||
|
ATTR_CMN_GEN_COUNT = 0x80000
|
||||||
|
ATTR_CMN_GRPID = 0x10000
|
||||||
|
ATTR_CMN_GRPUUID = 0x1000000
|
||||||
|
ATTR_CMN_MODTIME = 0x400
|
||||||
|
ATTR_CMN_NAME = 0x1
|
||||||
|
ATTR_CMN_NAMEDATTRCOUNT = 0x80000
|
||||||
|
ATTR_CMN_NAMEDATTRLIST = 0x100000
|
||||||
|
ATTR_CMN_OBJID = 0x20
|
||||||
|
ATTR_CMN_OBJPERMANENTID = 0x40
|
||||||
|
ATTR_CMN_OBJTAG = 0x10
|
||||||
|
ATTR_CMN_OBJTYPE = 0x8
|
||||||
|
ATTR_CMN_OWNERID = 0x8000
|
||||||
|
ATTR_CMN_PARENTID = 0x4000000
|
||||||
|
ATTR_CMN_PAROBJID = 0x80
|
||||||
|
ATTR_CMN_RETURNED_ATTRS = 0x80000000
|
||||||
|
ATTR_CMN_SCRIPT = 0x100
|
||||||
|
ATTR_CMN_SETMASK = 0x41c7ff00
|
||||||
|
ATTR_CMN_USERACCESS = 0x200000
|
||||||
|
ATTR_CMN_UUID = 0x800000
|
||||||
|
ATTR_CMN_VALIDMASK = 0xffffffff
|
||||||
|
ATTR_CMN_VOLSETMASK = 0x6700
|
||||||
|
ATTR_FILE_ALLOCSIZE = 0x4
|
||||||
|
ATTR_FILE_CLUMPSIZE = 0x10
|
||||||
|
ATTR_FILE_DATAALLOCSIZE = 0x400
|
||||||
|
ATTR_FILE_DATAEXTENTS = 0x800
|
||||||
|
ATTR_FILE_DATALENGTH = 0x200
|
||||||
|
ATTR_FILE_DEVTYPE = 0x20
|
||||||
|
ATTR_FILE_FILETYPE = 0x40
|
||||||
|
ATTR_FILE_FORKCOUNT = 0x80
|
||||||
|
ATTR_FILE_FORKLIST = 0x100
|
||||||
|
ATTR_FILE_IOBLOCKSIZE = 0x8
|
||||||
|
ATTR_FILE_LINKCOUNT = 0x1
|
||||||
|
ATTR_FILE_RSRCALLOCSIZE = 0x2000
|
||||||
|
ATTR_FILE_RSRCEXTENTS = 0x4000
|
||||||
|
ATTR_FILE_RSRCLENGTH = 0x1000
|
||||||
|
ATTR_FILE_SETMASK = 0x20
|
||||||
|
ATTR_FILE_TOTALSIZE = 0x2
|
||||||
|
ATTR_FILE_VALIDMASK = 0x37ff
|
||||||
|
ATTR_VOL_ALLOCATIONCLUMP = 0x40
|
||||||
|
ATTR_VOL_ATTRIBUTES = 0x40000000
|
||||||
|
ATTR_VOL_CAPABILITIES = 0x20000
|
||||||
|
ATTR_VOL_DIRCOUNT = 0x400
|
||||||
|
ATTR_VOL_ENCODINGSUSED = 0x10000
|
||||||
|
ATTR_VOL_FILECOUNT = 0x200
|
||||||
|
ATTR_VOL_FSTYPE = 0x1
|
||||||
|
ATTR_VOL_INFO = 0x80000000
|
||||||
|
ATTR_VOL_IOBLOCKSIZE = 0x80
|
||||||
|
ATTR_VOL_MAXOBJCOUNT = 0x800
|
||||||
|
ATTR_VOL_MINALLOCATION = 0x20
|
||||||
|
ATTR_VOL_MOUNTEDDEVICE = 0x8000
|
||||||
|
ATTR_VOL_MOUNTFLAGS = 0x4000
|
||||||
|
ATTR_VOL_MOUNTPOINT = 0x1000
|
||||||
|
ATTR_VOL_NAME = 0x2000
|
||||||
|
ATTR_VOL_OBJCOUNT = 0x100
|
||||||
|
ATTR_VOL_QUOTA_SIZE = 0x10000000
|
||||||
|
ATTR_VOL_RESERVED_SIZE = 0x20000000
|
||||||
|
ATTR_VOL_SETMASK = 0x80002000
|
||||||
|
ATTR_VOL_SIGNATURE = 0x2
|
||||||
|
ATTR_VOL_SIZE = 0x4
|
||||||
|
ATTR_VOL_SPACEAVAIL = 0x10
|
||||||
|
ATTR_VOL_SPACEFREE = 0x8
|
||||||
|
ATTR_VOL_UUID = 0x40000
|
||||||
|
ATTR_VOL_VALIDMASK = 0xf007ffff
|
||||||
B0 = 0x0
|
B0 = 0x0
|
||||||
B110 = 0x6e
|
B110 = 0x6e
|
||||||
B115200 = 0x1c200
|
B115200 = 0x1c200
|
||||||
|
@ -169,6 +249,8 @@ const (
|
||||||
CSTOP = 0x13
|
CSTOP = 0x13
|
||||||
CSTOPB = 0x400
|
CSTOPB = 0x400
|
||||||
CSUSP = 0x1a
|
CSUSP = 0x1a
|
||||||
|
CTL_HW = 0x6
|
||||||
|
CTL_KERN = 0x1
|
||||||
CTL_MAXNAME = 0xc
|
CTL_MAXNAME = 0xc
|
||||||
CTL_NET = 0x4
|
CTL_NET = 0x4
|
||||||
DLT_A429 = 0xb8
|
DLT_A429 = 0xb8
|
||||||
|
@ -390,6 +472,11 @@ const (
|
||||||
FF1 = 0x4000
|
FF1 = 0x4000
|
||||||
FFDLY = 0x4000
|
FFDLY = 0x4000
|
||||||
FLUSHO = 0x800000
|
FLUSHO = 0x800000
|
||||||
|
FSOPT_ATTR_CMN_EXTENDED = 0x20
|
||||||
|
FSOPT_NOFOLLOW = 0x1
|
||||||
|
FSOPT_NOINMEMUPDATE = 0x2
|
||||||
|
FSOPT_PACK_INVAL_ATTRS = 0x8
|
||||||
|
FSOPT_REPORT_FULLSIZE = 0x4
|
||||||
F_ADDFILESIGS = 0x3d
|
F_ADDFILESIGS = 0x3d
|
||||||
F_ADDFILESIGS_FOR_DYLD_SIM = 0x53
|
F_ADDFILESIGS_FOR_DYLD_SIM = 0x53
|
||||||
F_ADDFILESIGS_RETURN = 0x61
|
F_ADDFILESIGS_RETURN = 0x61
|
||||||
|
@ -425,6 +512,7 @@ const (
|
||||||
F_PATHPKG_CHECK = 0x34
|
F_PATHPKG_CHECK = 0x34
|
||||||
F_PEOFPOSMODE = 0x3
|
F_PEOFPOSMODE = 0x3
|
||||||
F_PREALLOCATE = 0x2a
|
F_PREALLOCATE = 0x2a
|
||||||
|
F_PUNCHHOLE = 0x63
|
||||||
F_RDADVISE = 0x2c
|
F_RDADVISE = 0x2c
|
||||||
F_RDAHEAD = 0x2d
|
F_RDAHEAD = 0x2d
|
||||||
F_RDLCK = 0x1
|
F_RDLCK = 0x1
|
||||||
|
@ -441,10 +529,12 @@ const (
|
||||||
F_SINGLE_WRITER = 0x4c
|
F_SINGLE_WRITER = 0x4c
|
||||||
F_THAW_FS = 0x36
|
F_THAW_FS = 0x36
|
||||||
F_TRANSCODEKEY = 0x4b
|
F_TRANSCODEKEY = 0x4b
|
||||||
|
F_TRIM_ACTIVE_FILE = 0x64
|
||||||
F_UNLCK = 0x2
|
F_UNLCK = 0x2
|
||||||
F_VOLPOSMODE = 0x4
|
F_VOLPOSMODE = 0x4
|
||||||
F_WRLCK = 0x3
|
F_WRLCK = 0x3
|
||||||
HUPCL = 0x4000
|
HUPCL = 0x4000
|
||||||
|
HW_MACHINE = 0x1
|
||||||
ICANON = 0x100
|
ICANON = 0x100
|
||||||
ICMP6_FILTER = 0x12
|
ICMP6_FILTER = 0x12
|
||||||
ICRNL = 0x100
|
ICRNL = 0x100
|
||||||
|
@ -681,6 +771,7 @@ const (
|
||||||
IPV6_FAITH = 0x1d
|
IPV6_FAITH = 0x1d
|
||||||
IPV6_FLOWINFO_MASK = 0xffffff0f
|
IPV6_FLOWINFO_MASK = 0xffffff0f
|
||||||
IPV6_FLOWLABEL_MASK = 0xffff0f00
|
IPV6_FLOWLABEL_MASK = 0xffff0f00
|
||||||
|
IPV6_FLOW_ECN_MASK = 0x300
|
||||||
IPV6_FRAGTTL = 0x3c
|
IPV6_FRAGTTL = 0x3c
|
||||||
IPV6_FW_ADD = 0x1e
|
IPV6_FW_ADD = 0x1e
|
||||||
IPV6_FW_DEL = 0x1f
|
IPV6_FW_DEL = 0x1f
|
||||||
|
@ -771,6 +862,7 @@ const (
|
||||||
IP_RECVOPTS = 0x5
|
IP_RECVOPTS = 0x5
|
||||||
IP_RECVPKTINFO = 0x1a
|
IP_RECVPKTINFO = 0x1a
|
||||||
IP_RECVRETOPTS = 0x6
|
IP_RECVRETOPTS = 0x6
|
||||||
|
IP_RECVTOS = 0x1b
|
||||||
IP_RECVTTL = 0x18
|
IP_RECVTTL = 0x18
|
||||||
IP_RETOPTS = 0x8
|
IP_RETOPTS = 0x8
|
||||||
IP_RF = 0x8000
|
IP_RF = 0x8000
|
||||||
|
@ -789,6 +881,10 @@ const (
|
||||||
IXANY = 0x800
|
IXANY = 0x800
|
||||||
IXOFF = 0x400
|
IXOFF = 0x400
|
||||||
IXON = 0x200
|
IXON = 0x200
|
||||||
|
KERN_HOSTNAME = 0xa
|
||||||
|
KERN_OSRELEASE = 0x2
|
||||||
|
KERN_OSTYPE = 0x1
|
||||||
|
KERN_VERSION = 0x4
|
||||||
LOCK_EX = 0x2
|
LOCK_EX = 0x2
|
||||||
LOCK_NB = 0x4
|
LOCK_NB = 0x4
|
||||||
LOCK_SH = 0x1
|
LOCK_SH = 0x1
|
||||||
|
|
|
@ -49,6 +49,86 @@ const (
|
||||||
AF_UNSPEC = 0x0
|
AF_UNSPEC = 0x0
|
||||||
AF_UTUN = 0x26
|
AF_UTUN = 0x26
|
||||||
ALTWERASE = 0x200
|
ALTWERASE = 0x200
|
||||||
|
ATTR_BIT_MAP_COUNT = 0x5
|
||||||
|
ATTR_CMN_ACCESSMASK = 0x20000
|
||||||
|
ATTR_CMN_ACCTIME = 0x1000
|
||||||
|
ATTR_CMN_ADDEDTIME = 0x10000000
|
||||||
|
ATTR_CMN_BKUPTIME = 0x2000
|
||||||
|
ATTR_CMN_CHGTIME = 0x800
|
||||||
|
ATTR_CMN_CRTIME = 0x200
|
||||||
|
ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000
|
||||||
|
ATTR_CMN_DEVID = 0x2
|
||||||
|
ATTR_CMN_DOCUMENT_ID = 0x100000
|
||||||
|
ATTR_CMN_ERROR = 0x20000000
|
||||||
|
ATTR_CMN_EXTENDED_SECURITY = 0x400000
|
||||||
|
ATTR_CMN_FILEID = 0x2000000
|
||||||
|
ATTR_CMN_FLAGS = 0x40000
|
||||||
|
ATTR_CMN_FNDRINFO = 0x4000
|
||||||
|
ATTR_CMN_FSID = 0x4
|
||||||
|
ATTR_CMN_FULLPATH = 0x8000000
|
||||||
|
ATTR_CMN_GEN_COUNT = 0x80000
|
||||||
|
ATTR_CMN_GRPID = 0x10000
|
||||||
|
ATTR_CMN_GRPUUID = 0x1000000
|
||||||
|
ATTR_CMN_MODTIME = 0x400
|
||||||
|
ATTR_CMN_NAME = 0x1
|
||||||
|
ATTR_CMN_NAMEDATTRCOUNT = 0x80000
|
||||||
|
ATTR_CMN_NAMEDATTRLIST = 0x100000
|
||||||
|
ATTR_CMN_OBJID = 0x20
|
||||||
|
ATTR_CMN_OBJPERMANENTID = 0x40
|
||||||
|
ATTR_CMN_OBJTAG = 0x10
|
||||||
|
ATTR_CMN_OBJTYPE = 0x8
|
||||||
|
ATTR_CMN_OWNERID = 0x8000
|
||||||
|
ATTR_CMN_PARENTID = 0x4000000
|
||||||
|
ATTR_CMN_PAROBJID = 0x80
|
||||||
|
ATTR_CMN_RETURNED_ATTRS = 0x80000000
|
||||||
|
ATTR_CMN_SCRIPT = 0x100
|
||||||
|
ATTR_CMN_SETMASK = 0x41c7ff00
|
||||||
|
ATTR_CMN_USERACCESS = 0x200000
|
||||||
|
ATTR_CMN_UUID = 0x800000
|
||||||
|
ATTR_CMN_VALIDMASK = 0xffffffff
|
||||||
|
ATTR_CMN_VOLSETMASK = 0x6700
|
||||||
|
ATTR_FILE_ALLOCSIZE = 0x4
|
||||||
|
ATTR_FILE_CLUMPSIZE = 0x10
|
||||||
|
ATTR_FILE_DATAALLOCSIZE = 0x400
|
||||||
|
ATTR_FILE_DATAEXTENTS = 0x800
|
||||||
|
ATTR_FILE_DATALENGTH = 0x200
|
||||||
|
ATTR_FILE_DEVTYPE = 0x20
|
||||||
|
ATTR_FILE_FILETYPE = 0x40
|
||||||
|
ATTR_FILE_FORKCOUNT = 0x80
|
||||||
|
ATTR_FILE_FORKLIST = 0x100
|
||||||
|
ATTR_FILE_IOBLOCKSIZE = 0x8
|
||||||
|
ATTR_FILE_LINKCOUNT = 0x1
|
||||||
|
ATTR_FILE_RSRCALLOCSIZE = 0x2000
|
||||||
|
ATTR_FILE_RSRCEXTENTS = 0x4000
|
||||||
|
ATTR_FILE_RSRCLENGTH = 0x1000
|
||||||
|
ATTR_FILE_SETMASK = 0x20
|
||||||
|
ATTR_FILE_TOTALSIZE = 0x2
|
||||||
|
ATTR_FILE_VALIDMASK = 0x37ff
|
||||||
|
ATTR_VOL_ALLOCATIONCLUMP = 0x40
|
||||||
|
ATTR_VOL_ATTRIBUTES = 0x40000000
|
||||||
|
ATTR_VOL_CAPABILITIES = 0x20000
|
||||||
|
ATTR_VOL_DIRCOUNT = 0x400
|
||||||
|
ATTR_VOL_ENCODINGSUSED = 0x10000
|
||||||
|
ATTR_VOL_FILECOUNT = 0x200
|
||||||
|
ATTR_VOL_FSTYPE = 0x1
|
||||||
|
ATTR_VOL_INFO = 0x80000000
|
||||||
|
ATTR_VOL_IOBLOCKSIZE = 0x80
|
||||||
|
ATTR_VOL_MAXOBJCOUNT = 0x800
|
||||||
|
ATTR_VOL_MINALLOCATION = 0x20
|
||||||
|
ATTR_VOL_MOUNTEDDEVICE = 0x8000
|
||||||
|
ATTR_VOL_MOUNTFLAGS = 0x4000
|
||||||
|
ATTR_VOL_MOUNTPOINT = 0x1000
|
||||||
|
ATTR_VOL_NAME = 0x2000
|
||||||
|
ATTR_VOL_OBJCOUNT = 0x100
|
||||||
|
ATTR_VOL_QUOTA_SIZE = 0x10000000
|
||||||
|
ATTR_VOL_RESERVED_SIZE = 0x20000000
|
||||||
|
ATTR_VOL_SETMASK = 0x80002000
|
||||||
|
ATTR_VOL_SIGNATURE = 0x2
|
||||||
|
ATTR_VOL_SIZE = 0x4
|
||||||
|
ATTR_VOL_SPACEAVAIL = 0x10
|
||||||
|
ATTR_VOL_SPACEFREE = 0x8
|
||||||
|
ATTR_VOL_UUID = 0x40000
|
||||||
|
ATTR_VOL_VALIDMASK = 0xf007ffff
|
||||||
B0 = 0x0
|
B0 = 0x0
|
||||||
B110 = 0x6e
|
B110 = 0x6e
|
||||||
B115200 = 0x1c200
|
B115200 = 0x1c200
|
||||||
|
@ -169,6 +249,8 @@ const (
|
||||||
CSTOP = 0x13
|
CSTOP = 0x13
|
||||||
CSTOPB = 0x400
|
CSTOPB = 0x400
|
||||||
CSUSP = 0x1a
|
CSUSP = 0x1a
|
||||||
|
CTL_HW = 0x6
|
||||||
|
CTL_KERN = 0x1
|
||||||
CTL_MAXNAME = 0xc
|
CTL_MAXNAME = 0xc
|
||||||
CTL_NET = 0x4
|
CTL_NET = 0x4
|
||||||
DLT_A429 = 0xb8
|
DLT_A429 = 0xb8
|
||||||
|
@ -390,6 +472,11 @@ const (
|
||||||
FF1 = 0x4000
|
FF1 = 0x4000
|
||||||
FFDLY = 0x4000
|
FFDLY = 0x4000
|
||||||
FLUSHO = 0x800000
|
FLUSHO = 0x800000
|
||||||
|
FSOPT_ATTR_CMN_EXTENDED = 0x20
|
||||||
|
FSOPT_NOFOLLOW = 0x1
|
||||||
|
FSOPT_NOINMEMUPDATE = 0x2
|
||||||
|
FSOPT_PACK_INVAL_ATTRS = 0x8
|
||||||
|
FSOPT_REPORT_FULLSIZE = 0x4
|
||||||
F_ADDFILESIGS = 0x3d
|
F_ADDFILESIGS = 0x3d
|
||||||
F_ADDFILESIGS_FOR_DYLD_SIM = 0x53
|
F_ADDFILESIGS_FOR_DYLD_SIM = 0x53
|
||||||
F_ADDFILESIGS_RETURN = 0x61
|
F_ADDFILESIGS_RETURN = 0x61
|
||||||
|
@ -425,6 +512,7 @@ const (
|
||||||
F_PATHPKG_CHECK = 0x34
|
F_PATHPKG_CHECK = 0x34
|
||||||
F_PEOFPOSMODE = 0x3
|
F_PEOFPOSMODE = 0x3
|
||||||
F_PREALLOCATE = 0x2a
|
F_PREALLOCATE = 0x2a
|
||||||
|
F_PUNCHHOLE = 0x63
|
||||||
F_RDADVISE = 0x2c
|
F_RDADVISE = 0x2c
|
||||||
F_RDAHEAD = 0x2d
|
F_RDAHEAD = 0x2d
|
||||||
F_RDLCK = 0x1
|
F_RDLCK = 0x1
|
||||||
|
@ -441,10 +529,12 @@ const (
|
||||||
F_SINGLE_WRITER = 0x4c
|
F_SINGLE_WRITER = 0x4c
|
||||||
F_THAW_FS = 0x36
|
F_THAW_FS = 0x36
|
||||||
F_TRANSCODEKEY = 0x4b
|
F_TRANSCODEKEY = 0x4b
|
||||||
|
F_TRIM_ACTIVE_FILE = 0x64
|
||||||
F_UNLCK = 0x2
|
F_UNLCK = 0x2
|
||||||
F_VOLPOSMODE = 0x4
|
F_VOLPOSMODE = 0x4
|
||||||
F_WRLCK = 0x3
|
F_WRLCK = 0x3
|
||||||
HUPCL = 0x4000
|
HUPCL = 0x4000
|
||||||
|
HW_MACHINE = 0x1
|
||||||
ICANON = 0x100
|
ICANON = 0x100
|
||||||
ICMP6_FILTER = 0x12
|
ICMP6_FILTER = 0x12
|
||||||
ICRNL = 0x100
|
ICRNL = 0x100
|
||||||
|
@ -681,6 +771,7 @@ const (
|
||||||
IPV6_FAITH = 0x1d
|
IPV6_FAITH = 0x1d
|
||||||
IPV6_FLOWINFO_MASK = 0xffffff0f
|
IPV6_FLOWINFO_MASK = 0xffffff0f
|
||||||
IPV6_FLOWLABEL_MASK = 0xffff0f00
|
IPV6_FLOWLABEL_MASK = 0xffff0f00
|
||||||
|
IPV6_FLOW_ECN_MASK = 0x300
|
||||||
IPV6_FRAGTTL = 0x3c
|
IPV6_FRAGTTL = 0x3c
|
||||||
IPV6_FW_ADD = 0x1e
|
IPV6_FW_ADD = 0x1e
|
||||||
IPV6_FW_DEL = 0x1f
|
IPV6_FW_DEL = 0x1f
|
||||||
|
@ -771,6 +862,7 @@ const (
|
||||||
IP_RECVOPTS = 0x5
|
IP_RECVOPTS = 0x5
|
||||||
IP_RECVPKTINFO = 0x1a
|
IP_RECVPKTINFO = 0x1a
|
||||||
IP_RECVRETOPTS = 0x6
|
IP_RECVRETOPTS = 0x6
|
||||||
|
IP_RECVTOS = 0x1b
|
||||||
IP_RECVTTL = 0x18
|
IP_RECVTTL = 0x18
|
||||||
IP_RETOPTS = 0x8
|
IP_RETOPTS = 0x8
|
||||||
IP_RF = 0x8000
|
IP_RF = 0x8000
|
||||||
|
@ -789,6 +881,10 @@ const (
|
||||||
IXANY = 0x800
|
IXANY = 0x800
|
||||||
IXOFF = 0x400
|
IXOFF = 0x400
|
||||||
IXON = 0x200
|
IXON = 0x200
|
||||||
|
KERN_HOSTNAME = 0xa
|
||||||
|
KERN_OSRELEASE = 0x2
|
||||||
|
KERN_OSTYPE = 0x1
|
||||||
|
KERN_VERSION = 0x4
|
||||||
LOCK_EX = 0x2
|
LOCK_EX = 0x2
|
||||||
LOCK_NB = 0x4
|
LOCK_NB = 0x4
|
||||||
LOCK_SH = 0x1
|
LOCK_SH = 0x1
|
||||||
|
|
|
@ -168,6 +168,8 @@ const (
|
||||||
CSTOP = 0x13
|
CSTOP = 0x13
|
||||||
CSTOPB = 0x400
|
CSTOPB = 0x400
|
||||||
CSUSP = 0x1a
|
CSUSP = 0x1a
|
||||||
|
CTL_HW = 0x6
|
||||||
|
CTL_KERN = 0x1
|
||||||
CTL_MAXNAME = 0xc
|
CTL_MAXNAME = 0xc
|
||||||
CTL_NET = 0x4
|
CTL_NET = 0x4
|
||||||
DLT_A429 = 0xb8
|
DLT_A429 = 0xb8
|
||||||
|
@ -353,6 +355,7 @@ const (
|
||||||
F_UNLCK = 0x2
|
F_UNLCK = 0x2
|
||||||
F_WRLCK = 0x3
|
F_WRLCK = 0x3
|
||||||
HUPCL = 0x4000
|
HUPCL = 0x4000
|
||||||
|
HW_MACHINE = 0x1
|
||||||
ICANON = 0x100
|
ICANON = 0x100
|
||||||
ICMP6_FILTER = 0x12
|
ICMP6_FILTER = 0x12
|
||||||
ICRNL = 0x100
|
ICRNL = 0x100
|
||||||
|
@ -835,6 +838,10 @@ const (
|
||||||
IXANY = 0x800
|
IXANY = 0x800
|
||||||
IXOFF = 0x400
|
IXOFF = 0x400
|
||||||
IXON = 0x200
|
IXON = 0x200
|
||||||
|
KERN_HOSTNAME = 0xa
|
||||||
|
KERN_OSRELEASE = 0x2
|
||||||
|
KERN_OSTYPE = 0x1
|
||||||
|
KERN_VERSION = 0x4
|
||||||
LOCK_EX = 0x2
|
LOCK_EX = 0x2
|
||||||
LOCK_NB = 0x4
|
LOCK_NB = 0x4
|
||||||
LOCK_SH = 0x1
|
LOCK_SH = 0x1
|
||||||
|
|
|
@ -351,6 +351,8 @@ const (
|
||||||
CSTOP = 0x13
|
CSTOP = 0x13
|
||||||
CSTOPB = 0x400
|
CSTOPB = 0x400
|
||||||
CSUSP = 0x1a
|
CSUSP = 0x1a
|
||||||
|
CTL_HW = 0x6
|
||||||
|
CTL_KERN = 0x1
|
||||||
CTL_MAXNAME = 0x18
|
CTL_MAXNAME = 0x18
|
||||||
CTL_NET = 0x4
|
CTL_NET = 0x4
|
||||||
DLT_A429 = 0xb8
|
DLT_A429 = 0xb8
|
||||||
|
@ -608,6 +610,7 @@ const (
|
||||||
F_UNLCKSYS = 0x4
|
F_UNLCKSYS = 0x4
|
||||||
F_WRLCK = 0x3
|
F_WRLCK = 0x3
|
||||||
HUPCL = 0x4000
|
HUPCL = 0x4000
|
||||||
|
HW_MACHINE = 0x1
|
||||||
ICANON = 0x100
|
ICANON = 0x100
|
||||||
ICMP6_FILTER = 0x12
|
ICMP6_FILTER = 0x12
|
||||||
ICRNL = 0x100
|
ICRNL = 0x100
|
||||||
|
@ -944,6 +947,10 @@ const (
|
||||||
IXANY = 0x800
|
IXANY = 0x800
|
||||||
IXOFF = 0x400
|
IXOFF = 0x400
|
||||||
IXON = 0x200
|
IXON = 0x200
|
||||||
|
KERN_HOSTNAME = 0xa
|
||||||
|
KERN_OSRELEASE = 0x2
|
||||||
|
KERN_OSTYPE = 0x1
|
||||||
|
KERN_VERSION = 0x4
|
||||||
LOCK_EX = 0x2
|
LOCK_EX = 0x2
|
||||||
LOCK_NB = 0x4
|
LOCK_NB = 0x4
|
||||||
LOCK_SH = 0x1
|
LOCK_SH = 0x1
|
||||||
|
|
|
@ -351,6 +351,8 @@ const (
|
||||||
CSTOP = 0x13
|
CSTOP = 0x13
|
||||||
CSTOPB = 0x400
|
CSTOPB = 0x400
|
||||||
CSUSP = 0x1a
|
CSUSP = 0x1a
|
||||||
|
CTL_HW = 0x6
|
||||||
|
CTL_KERN = 0x1
|
||||||
CTL_MAXNAME = 0x18
|
CTL_MAXNAME = 0x18
|
||||||
CTL_NET = 0x4
|
CTL_NET = 0x4
|
||||||
DLT_A429 = 0xb8
|
DLT_A429 = 0xb8
|
||||||
|
@ -608,6 +610,7 @@ const (
|
||||||
F_UNLCKSYS = 0x4
|
F_UNLCKSYS = 0x4
|
||||||
F_WRLCK = 0x3
|
F_WRLCK = 0x3
|
||||||
HUPCL = 0x4000
|
HUPCL = 0x4000
|
||||||
|
HW_MACHINE = 0x1
|
||||||
ICANON = 0x100
|
ICANON = 0x100
|
||||||
ICMP6_FILTER = 0x12
|
ICMP6_FILTER = 0x12
|
||||||
ICRNL = 0x100
|
ICRNL = 0x100
|
||||||
|
@ -944,6 +947,10 @@ const (
|
||||||
IXANY = 0x800
|
IXANY = 0x800
|
||||||
IXOFF = 0x400
|
IXOFF = 0x400
|
||||||
IXON = 0x200
|
IXON = 0x200
|
||||||
|
KERN_HOSTNAME = 0xa
|
||||||
|
KERN_OSRELEASE = 0x2
|
||||||
|
KERN_OSTYPE = 0x1
|
||||||
|
KERN_VERSION = 0x4
|
||||||
LOCK_EX = 0x2
|
LOCK_EX = 0x2
|
||||||
LOCK_NB = 0x4
|
LOCK_NB = 0x4
|
||||||
LOCK_SH = 0x1
|
LOCK_SH = 0x1
|
||||||
|
|
|
@ -351,6 +351,8 @@ const (
|
||||||
CSTOP = 0x13
|
CSTOP = 0x13
|
||||||
CSTOPB = 0x400
|
CSTOPB = 0x400
|
||||||
CSUSP = 0x1a
|
CSUSP = 0x1a
|
||||||
|
CTL_HW = 0x6
|
||||||
|
CTL_KERN = 0x1
|
||||||
CTL_MAXNAME = 0x18
|
CTL_MAXNAME = 0x18
|
||||||
CTL_NET = 0x4
|
CTL_NET = 0x4
|
||||||
DLT_A429 = 0xb8
|
DLT_A429 = 0xb8
|
||||||
|
@ -615,6 +617,7 @@ const (
|
||||||
F_UNLCKSYS = 0x4
|
F_UNLCKSYS = 0x4
|
||||||
F_WRLCK = 0x3
|
F_WRLCK = 0x3
|
||||||
HUPCL = 0x4000
|
HUPCL = 0x4000
|
||||||
|
HW_MACHINE = 0x1
|
||||||
ICANON = 0x100
|
ICANON = 0x100
|
||||||
ICMP6_FILTER = 0x12
|
ICMP6_FILTER = 0x12
|
||||||
ICRNL = 0x100
|
ICRNL = 0x100
|
||||||
|
@ -951,6 +954,10 @@ const (
|
||||||
IXANY = 0x800
|
IXANY = 0x800
|
||||||
IXOFF = 0x400
|
IXOFF = 0x400
|
||||||
IXON = 0x200
|
IXON = 0x200
|
||||||
|
KERN_HOSTNAME = 0xa
|
||||||
|
KERN_OSRELEASE = 0x2
|
||||||
|
KERN_OSTYPE = 0x1
|
||||||
|
KERN_VERSION = 0x4
|
||||||
LOCK_EX = 0x2
|
LOCK_EX = 0x2
|
||||||
LOCK_NB = 0x4
|
LOCK_NB = 0x4
|
||||||
LOCK_SH = 0x1
|
LOCK_SH = 0x1
|
||||||
|
|
|
@ -623,6 +623,7 @@ const (
|
||||||
IN_OPEN = 0x20
|
IN_OPEN = 0x20
|
||||||
IN_Q_OVERFLOW = 0x4000
|
IN_Q_OVERFLOW = 0x4000
|
||||||
IN_UNMOUNT = 0x2000
|
IN_UNMOUNT = 0x2000
|
||||||
|
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
|
||||||
IPPROTO_AH = 0x33
|
IPPROTO_AH = 0x33
|
||||||
IPPROTO_BEETPH = 0x5e
|
IPPROTO_BEETPH = 0x5e
|
||||||
IPPROTO_COMP = 0x6c
|
IPPROTO_COMP = 0x6c
|
||||||
|
@ -1637,6 +1638,27 @@ const (
|
||||||
SPLICE_F_MORE = 0x4
|
SPLICE_F_MORE = 0x4
|
||||||
SPLICE_F_MOVE = 0x1
|
SPLICE_F_MOVE = 0x1
|
||||||
SPLICE_F_NONBLOCK = 0x2
|
SPLICE_F_NONBLOCK = 0x2
|
||||||
|
STATX_ALL = 0xfff
|
||||||
|
STATX_ATIME = 0x20
|
||||||
|
STATX_ATTR_APPEND = 0x20
|
||||||
|
STATX_ATTR_AUTOMOUNT = 0x1000
|
||||||
|
STATX_ATTR_COMPRESSED = 0x4
|
||||||
|
STATX_ATTR_ENCRYPTED = 0x800
|
||||||
|
STATX_ATTR_IMMUTABLE = 0x10
|
||||||
|
STATX_ATTR_NODUMP = 0x40
|
||||||
|
STATX_BASIC_STATS = 0x7ff
|
||||||
|
STATX_BLOCKS = 0x400
|
||||||
|
STATX_BTIME = 0x800
|
||||||
|
STATX_CTIME = 0x80
|
||||||
|
STATX_GID = 0x10
|
||||||
|
STATX_INO = 0x100
|
||||||
|
STATX_MODE = 0x2
|
||||||
|
STATX_MTIME = 0x40
|
||||||
|
STATX_NLINK = 0x4
|
||||||
|
STATX_SIZE = 0x200
|
||||||
|
STATX_TYPE = 0x1
|
||||||
|
STATX_UID = 0x8
|
||||||
|
STATX__RESERVED = 0x80000000
|
||||||
S_BLKSIZE = 0x200
|
S_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
|
|
@ -623,6 +623,7 @@ const (
|
||||||
IN_OPEN = 0x20
|
IN_OPEN = 0x20
|
||||||
IN_Q_OVERFLOW = 0x4000
|
IN_Q_OVERFLOW = 0x4000
|
||||||
IN_UNMOUNT = 0x2000
|
IN_UNMOUNT = 0x2000
|
||||||
|
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
|
||||||
IPPROTO_AH = 0x33
|
IPPROTO_AH = 0x33
|
||||||
IPPROTO_BEETPH = 0x5e
|
IPPROTO_BEETPH = 0x5e
|
||||||
IPPROTO_COMP = 0x6c
|
IPPROTO_COMP = 0x6c
|
||||||
|
@ -1638,6 +1639,27 @@ const (
|
||||||
SPLICE_F_MORE = 0x4
|
SPLICE_F_MORE = 0x4
|
||||||
SPLICE_F_MOVE = 0x1
|
SPLICE_F_MOVE = 0x1
|
||||||
SPLICE_F_NONBLOCK = 0x2
|
SPLICE_F_NONBLOCK = 0x2
|
||||||
|
STATX_ALL = 0xfff
|
||||||
|
STATX_ATIME = 0x20
|
||||||
|
STATX_ATTR_APPEND = 0x20
|
||||||
|
STATX_ATTR_AUTOMOUNT = 0x1000
|
||||||
|
STATX_ATTR_COMPRESSED = 0x4
|
||||||
|
STATX_ATTR_ENCRYPTED = 0x800
|
||||||
|
STATX_ATTR_IMMUTABLE = 0x10
|
||||||
|
STATX_ATTR_NODUMP = 0x40
|
||||||
|
STATX_BASIC_STATS = 0x7ff
|
||||||
|
STATX_BLOCKS = 0x400
|
||||||
|
STATX_BTIME = 0x800
|
||||||
|
STATX_CTIME = 0x80
|
||||||
|
STATX_GID = 0x10
|
||||||
|
STATX_INO = 0x100
|
||||||
|
STATX_MODE = 0x2
|
||||||
|
STATX_MTIME = 0x40
|
||||||
|
STATX_NLINK = 0x4
|
||||||
|
STATX_SIZE = 0x200
|
||||||
|
STATX_TYPE = 0x1
|
||||||
|
STATX_UID = 0x8
|
||||||
|
STATX__RESERVED = 0x80000000
|
||||||
S_BLKSIZE = 0x200
|
S_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
|
|
@ -623,6 +623,7 @@ const (
|
||||||
IN_OPEN = 0x20
|
IN_OPEN = 0x20
|
||||||
IN_Q_OVERFLOW = 0x4000
|
IN_Q_OVERFLOW = 0x4000
|
||||||
IN_UNMOUNT = 0x2000
|
IN_UNMOUNT = 0x2000
|
||||||
|
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
|
||||||
IPPROTO_AH = 0x33
|
IPPROTO_AH = 0x33
|
||||||
IPPROTO_BEETPH = 0x5e
|
IPPROTO_BEETPH = 0x5e
|
||||||
IPPROTO_COMP = 0x6c
|
IPPROTO_COMP = 0x6c
|
||||||
|
@ -1642,6 +1643,27 @@ const (
|
||||||
SPLICE_F_MORE = 0x4
|
SPLICE_F_MORE = 0x4
|
||||||
SPLICE_F_MOVE = 0x1
|
SPLICE_F_MOVE = 0x1
|
||||||
SPLICE_F_NONBLOCK = 0x2
|
SPLICE_F_NONBLOCK = 0x2
|
||||||
|
STATX_ALL = 0xfff
|
||||||
|
STATX_ATIME = 0x20
|
||||||
|
STATX_ATTR_APPEND = 0x20
|
||||||
|
STATX_ATTR_AUTOMOUNT = 0x1000
|
||||||
|
STATX_ATTR_COMPRESSED = 0x4
|
||||||
|
STATX_ATTR_ENCRYPTED = 0x800
|
||||||
|
STATX_ATTR_IMMUTABLE = 0x10
|
||||||
|
STATX_ATTR_NODUMP = 0x40
|
||||||
|
STATX_BASIC_STATS = 0x7ff
|
||||||
|
STATX_BLOCKS = 0x400
|
||||||
|
STATX_BTIME = 0x800
|
||||||
|
STATX_CTIME = 0x80
|
||||||
|
STATX_GID = 0x10
|
||||||
|
STATX_INO = 0x100
|
||||||
|
STATX_MODE = 0x2
|
||||||
|
STATX_MTIME = 0x40
|
||||||
|
STATX_NLINK = 0x4
|
||||||
|
STATX_SIZE = 0x200
|
||||||
|
STATX_TYPE = 0x1
|
||||||
|
STATX_UID = 0x8
|
||||||
|
STATX__RESERVED = 0x80000000
|
||||||
S_BLKSIZE = 0x200
|
S_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
|
|
@ -625,6 +625,7 @@ const (
|
||||||
IN_OPEN = 0x20
|
IN_OPEN = 0x20
|
||||||
IN_Q_OVERFLOW = 0x4000
|
IN_Q_OVERFLOW = 0x4000
|
||||||
IN_UNMOUNT = 0x2000
|
IN_UNMOUNT = 0x2000
|
||||||
|
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
|
||||||
IPPROTO_AH = 0x33
|
IPPROTO_AH = 0x33
|
||||||
IPPROTO_BEETPH = 0x5e
|
IPPROTO_BEETPH = 0x5e
|
||||||
IPPROTO_COMP = 0x6c
|
IPPROTO_COMP = 0x6c
|
||||||
|
@ -1628,6 +1629,27 @@ const (
|
||||||
SPLICE_F_MORE = 0x4
|
SPLICE_F_MORE = 0x4
|
||||||
SPLICE_F_MOVE = 0x1
|
SPLICE_F_MOVE = 0x1
|
||||||
SPLICE_F_NONBLOCK = 0x2
|
SPLICE_F_NONBLOCK = 0x2
|
||||||
|
STATX_ALL = 0xfff
|
||||||
|
STATX_ATIME = 0x20
|
||||||
|
STATX_ATTR_APPEND = 0x20
|
||||||
|
STATX_ATTR_AUTOMOUNT = 0x1000
|
||||||
|
STATX_ATTR_COMPRESSED = 0x4
|
||||||
|
STATX_ATTR_ENCRYPTED = 0x800
|
||||||
|
STATX_ATTR_IMMUTABLE = 0x10
|
||||||
|
STATX_ATTR_NODUMP = 0x40
|
||||||
|
STATX_BASIC_STATS = 0x7ff
|
||||||
|
STATX_BLOCKS = 0x400
|
||||||
|
STATX_BTIME = 0x800
|
||||||
|
STATX_CTIME = 0x80
|
||||||
|
STATX_GID = 0x10
|
||||||
|
STATX_INO = 0x100
|
||||||
|
STATX_MODE = 0x2
|
||||||
|
STATX_MTIME = 0x40
|
||||||
|
STATX_NLINK = 0x4
|
||||||
|
STATX_SIZE = 0x200
|
||||||
|
STATX_TYPE = 0x1
|
||||||
|
STATX_UID = 0x8
|
||||||
|
STATX__RESERVED = 0x80000000
|
||||||
S_BLKSIZE = 0x200
|
S_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
|
|
@ -623,6 +623,7 @@ const (
|
||||||
IN_OPEN = 0x20
|
IN_OPEN = 0x20
|
||||||
IN_Q_OVERFLOW = 0x4000
|
IN_Q_OVERFLOW = 0x4000
|
||||||
IN_UNMOUNT = 0x2000
|
IN_UNMOUNT = 0x2000
|
||||||
|
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
|
||||||
IPPROTO_AH = 0x33
|
IPPROTO_AH = 0x33
|
||||||
IPPROTO_BEETPH = 0x5e
|
IPPROTO_BEETPH = 0x5e
|
||||||
IPPROTO_COMP = 0x6c
|
IPPROTO_COMP = 0x6c
|
||||||
|
@ -1640,6 +1641,27 @@ const (
|
||||||
SPLICE_F_MORE = 0x4
|
SPLICE_F_MORE = 0x4
|
||||||
SPLICE_F_MOVE = 0x1
|
SPLICE_F_MOVE = 0x1
|
||||||
SPLICE_F_NONBLOCK = 0x2
|
SPLICE_F_NONBLOCK = 0x2
|
||||||
|
STATX_ALL = 0xfff
|
||||||
|
STATX_ATIME = 0x20
|
||||||
|
STATX_ATTR_APPEND = 0x20
|
||||||
|
STATX_ATTR_AUTOMOUNT = 0x1000
|
||||||
|
STATX_ATTR_COMPRESSED = 0x4
|
||||||
|
STATX_ATTR_ENCRYPTED = 0x800
|
||||||
|
STATX_ATTR_IMMUTABLE = 0x10
|
||||||
|
STATX_ATTR_NODUMP = 0x40
|
||||||
|
STATX_BASIC_STATS = 0x7ff
|
||||||
|
STATX_BLOCKS = 0x400
|
||||||
|
STATX_BTIME = 0x800
|
||||||
|
STATX_CTIME = 0x80
|
||||||
|
STATX_GID = 0x10
|
||||||
|
STATX_INO = 0x100
|
||||||
|
STATX_MODE = 0x2
|
||||||
|
STATX_MTIME = 0x40
|
||||||
|
STATX_NLINK = 0x4
|
||||||
|
STATX_SIZE = 0x200
|
||||||
|
STATX_TYPE = 0x1
|
||||||
|
STATX_UID = 0x8
|
||||||
|
STATX__RESERVED = 0x80000000
|
||||||
S_BLKSIZE = 0x200
|
S_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
|
|
@ -623,6 +623,7 @@ const (
|
||||||
IN_OPEN = 0x20
|
IN_OPEN = 0x20
|
||||||
IN_Q_OVERFLOW = 0x4000
|
IN_Q_OVERFLOW = 0x4000
|
||||||
IN_UNMOUNT = 0x2000
|
IN_UNMOUNT = 0x2000
|
||||||
|
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
|
||||||
IPPROTO_AH = 0x33
|
IPPROTO_AH = 0x33
|
||||||
IPPROTO_BEETPH = 0x5e
|
IPPROTO_BEETPH = 0x5e
|
||||||
IPPROTO_COMP = 0x6c
|
IPPROTO_COMP = 0x6c
|
||||||
|
@ -1640,6 +1641,27 @@ const (
|
||||||
SPLICE_F_MORE = 0x4
|
SPLICE_F_MORE = 0x4
|
||||||
SPLICE_F_MOVE = 0x1
|
SPLICE_F_MOVE = 0x1
|
||||||
SPLICE_F_NONBLOCK = 0x2
|
SPLICE_F_NONBLOCK = 0x2
|
||||||
|
STATX_ALL = 0xfff
|
||||||
|
STATX_ATIME = 0x20
|
||||||
|
STATX_ATTR_APPEND = 0x20
|
||||||
|
STATX_ATTR_AUTOMOUNT = 0x1000
|
||||||
|
STATX_ATTR_COMPRESSED = 0x4
|
||||||
|
STATX_ATTR_ENCRYPTED = 0x800
|
||||||
|
STATX_ATTR_IMMUTABLE = 0x10
|
||||||
|
STATX_ATTR_NODUMP = 0x40
|
||||||
|
STATX_BASIC_STATS = 0x7ff
|
||||||
|
STATX_BLOCKS = 0x400
|
||||||
|
STATX_BTIME = 0x800
|
||||||
|
STATX_CTIME = 0x80
|
||||||
|
STATX_GID = 0x10
|
||||||
|
STATX_INO = 0x100
|
||||||
|
STATX_MODE = 0x2
|
||||||
|
STATX_MTIME = 0x40
|
||||||
|
STATX_NLINK = 0x4
|
||||||
|
STATX_SIZE = 0x200
|
||||||
|
STATX_TYPE = 0x1
|
||||||
|
STATX_UID = 0x8
|
||||||
|
STATX__RESERVED = 0x80000000
|
||||||
S_BLKSIZE = 0x200
|
S_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
|
|
@ -623,6 +623,7 @@ const (
|
||||||
IN_OPEN = 0x20
|
IN_OPEN = 0x20
|
||||||
IN_Q_OVERFLOW = 0x4000
|
IN_Q_OVERFLOW = 0x4000
|
||||||
IN_UNMOUNT = 0x2000
|
IN_UNMOUNT = 0x2000
|
||||||
|
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
|
||||||
IPPROTO_AH = 0x33
|
IPPROTO_AH = 0x33
|
||||||
IPPROTO_BEETPH = 0x5e
|
IPPROTO_BEETPH = 0x5e
|
||||||
IPPROTO_COMP = 0x6c
|
IPPROTO_COMP = 0x6c
|
||||||
|
@ -1640,6 +1641,27 @@ const (
|
||||||
SPLICE_F_MORE = 0x4
|
SPLICE_F_MORE = 0x4
|
||||||
SPLICE_F_MOVE = 0x1
|
SPLICE_F_MOVE = 0x1
|
||||||
SPLICE_F_NONBLOCK = 0x2
|
SPLICE_F_NONBLOCK = 0x2
|
||||||
|
STATX_ALL = 0xfff
|
||||||
|
STATX_ATIME = 0x20
|
||||||
|
STATX_ATTR_APPEND = 0x20
|
||||||
|
STATX_ATTR_AUTOMOUNT = 0x1000
|
||||||
|
STATX_ATTR_COMPRESSED = 0x4
|
||||||
|
STATX_ATTR_ENCRYPTED = 0x800
|
||||||
|
STATX_ATTR_IMMUTABLE = 0x10
|
||||||
|
STATX_ATTR_NODUMP = 0x40
|
||||||
|
STATX_BASIC_STATS = 0x7ff
|
||||||
|
STATX_BLOCKS = 0x400
|
||||||
|
STATX_BTIME = 0x800
|
||||||
|
STATX_CTIME = 0x80
|
||||||
|
STATX_GID = 0x10
|
||||||
|
STATX_INO = 0x100
|
||||||
|
STATX_MODE = 0x2
|
||||||
|
STATX_MTIME = 0x40
|
||||||
|
STATX_NLINK = 0x4
|
||||||
|
STATX_SIZE = 0x200
|
||||||
|
STATX_TYPE = 0x1
|
||||||
|
STATX_UID = 0x8
|
||||||
|
STATX__RESERVED = 0x80000000
|
||||||
S_BLKSIZE = 0x200
|
S_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
|
|
@ -623,6 +623,7 @@ const (
|
||||||
IN_OPEN = 0x20
|
IN_OPEN = 0x20
|
||||||
IN_Q_OVERFLOW = 0x4000
|
IN_Q_OVERFLOW = 0x4000
|
||||||
IN_UNMOUNT = 0x2000
|
IN_UNMOUNT = 0x2000
|
||||||
|
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
|
||||||
IPPROTO_AH = 0x33
|
IPPROTO_AH = 0x33
|
||||||
IPPROTO_BEETPH = 0x5e
|
IPPROTO_BEETPH = 0x5e
|
||||||
IPPROTO_COMP = 0x6c
|
IPPROTO_COMP = 0x6c
|
||||||
|
@ -1640,6 +1641,27 @@ const (
|
||||||
SPLICE_F_MORE = 0x4
|
SPLICE_F_MORE = 0x4
|
||||||
SPLICE_F_MOVE = 0x1
|
SPLICE_F_MOVE = 0x1
|
||||||
SPLICE_F_NONBLOCK = 0x2
|
SPLICE_F_NONBLOCK = 0x2
|
||||||
|
STATX_ALL = 0xfff
|
||||||
|
STATX_ATIME = 0x20
|
||||||
|
STATX_ATTR_APPEND = 0x20
|
||||||
|
STATX_ATTR_AUTOMOUNT = 0x1000
|
||||||
|
STATX_ATTR_COMPRESSED = 0x4
|
||||||
|
STATX_ATTR_ENCRYPTED = 0x800
|
||||||
|
STATX_ATTR_IMMUTABLE = 0x10
|
||||||
|
STATX_ATTR_NODUMP = 0x40
|
||||||
|
STATX_BASIC_STATS = 0x7ff
|
||||||
|
STATX_BLOCKS = 0x400
|
||||||
|
STATX_BTIME = 0x800
|
||||||
|
STATX_CTIME = 0x80
|
||||||
|
STATX_GID = 0x10
|
||||||
|
STATX_INO = 0x100
|
||||||
|
STATX_MODE = 0x2
|
||||||
|
STATX_MTIME = 0x40
|
||||||
|
STATX_NLINK = 0x4
|
||||||
|
STATX_SIZE = 0x200
|
||||||
|
STATX_TYPE = 0x1
|
||||||
|
STATX_UID = 0x8
|
||||||
|
STATX__RESERVED = 0x80000000
|
||||||
S_BLKSIZE = 0x200
|
S_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
|
|
@ -623,6 +623,7 @@ const (
|
||||||
IN_OPEN = 0x20
|
IN_OPEN = 0x20
|
||||||
IN_Q_OVERFLOW = 0x4000
|
IN_Q_OVERFLOW = 0x4000
|
||||||
IN_UNMOUNT = 0x2000
|
IN_UNMOUNT = 0x2000
|
||||||
|
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
|
||||||
IPPROTO_AH = 0x33
|
IPPROTO_AH = 0x33
|
||||||
IPPROTO_BEETPH = 0x5e
|
IPPROTO_BEETPH = 0x5e
|
||||||
IPPROTO_COMP = 0x6c
|
IPPROTO_COMP = 0x6c
|
||||||
|
@ -1695,6 +1696,27 @@ const (
|
||||||
SPLICE_F_MORE = 0x4
|
SPLICE_F_MORE = 0x4
|
||||||
SPLICE_F_MOVE = 0x1
|
SPLICE_F_MOVE = 0x1
|
||||||
SPLICE_F_NONBLOCK = 0x2
|
SPLICE_F_NONBLOCK = 0x2
|
||||||
|
STATX_ALL = 0xfff
|
||||||
|
STATX_ATIME = 0x20
|
||||||
|
STATX_ATTR_APPEND = 0x20
|
||||||
|
STATX_ATTR_AUTOMOUNT = 0x1000
|
||||||
|
STATX_ATTR_COMPRESSED = 0x4
|
||||||
|
STATX_ATTR_ENCRYPTED = 0x800
|
||||||
|
STATX_ATTR_IMMUTABLE = 0x10
|
||||||
|
STATX_ATTR_NODUMP = 0x40
|
||||||
|
STATX_BASIC_STATS = 0x7ff
|
||||||
|
STATX_BLOCKS = 0x400
|
||||||
|
STATX_BTIME = 0x800
|
||||||
|
STATX_CTIME = 0x80
|
||||||
|
STATX_GID = 0x10
|
||||||
|
STATX_INO = 0x100
|
||||||
|
STATX_MODE = 0x2
|
||||||
|
STATX_MTIME = 0x40
|
||||||
|
STATX_NLINK = 0x4
|
||||||
|
STATX_SIZE = 0x200
|
||||||
|
STATX_TYPE = 0x1
|
||||||
|
STATX_UID = 0x8
|
||||||
|
STATX__RESERVED = 0x80000000
|
||||||
S_BLKSIZE = 0x200
|
S_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
|
|
@ -623,6 +623,7 @@ const (
|
||||||
IN_OPEN = 0x20
|
IN_OPEN = 0x20
|
||||||
IN_Q_OVERFLOW = 0x4000
|
IN_Q_OVERFLOW = 0x4000
|
||||||
IN_UNMOUNT = 0x2000
|
IN_UNMOUNT = 0x2000
|
||||||
|
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9
|
||||||
IPPROTO_AH = 0x33
|
IPPROTO_AH = 0x33
|
||||||
IPPROTO_BEETPH = 0x5e
|
IPPROTO_BEETPH = 0x5e
|
||||||
IPPROTO_COMP = 0x6c
|
IPPROTO_COMP = 0x6c
|
||||||
|
@ -1695,6 +1696,27 @@ const (
|
||||||
SPLICE_F_MORE = 0x4
|
SPLICE_F_MORE = 0x4
|
||||||
SPLICE_F_MOVE = 0x1
|
SPLICE_F_MOVE = 0x1
|
||||||
SPLICE_F_NONBLOCK = 0x2
|
SPLICE_F_NONBLOCK = 0x2
|
||||||
|
STATX_ALL = 0xfff
|
||||||
|
STATX_ATIME = 0x20
|
||||||
|
STATX_ATTR_APPEND = 0x20
|
||||||
|
STATX_ATTR_AUTOMOUNT = 0x1000
|
||||||
|
STATX_ATTR_COMPRESSED = 0x4
|
||||||
|
STATX_ATTR_ENCRYPTED = 0x800
|
||||||
|
STATX_ATTR_IMMUTABLE = 0x10
|
||||||
|
STATX_ATTR_NODUMP = 0x40
|
||||||
|
STATX_BASIC_STATS = 0x7ff
|
||||||
|
STATX_BLOCKS = 0x400
|
||||||
|
STATX_BTIME = 0x800
|
||||||
|
STATX_CTIME = 0x80
|
||||||
|
STATX_GID = 0x10
|
||||||
|
STATX_INO = 0x100
|
||||||
|
STATX_MODE = 0x2
|
||||||
|
STATX_MTIME = 0x40
|
||||||
|
STATX_NLINK = 0x4
|
||||||
|
STATX_SIZE = 0x200
|
||||||
|
STATX_TYPE = 0x1
|
||||||
|
STATX_UID = 0x8
|
||||||
|
STATX__RESERVED = 0x80000000
|
||||||
S_BLKSIZE = 0x200
|
S_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
|
|
@ -623,6 +623,7 @@ const (
|
||||||
IN_OPEN = 0x20
|
IN_OPEN = 0x20
|
||||||
IN_Q_OVERFLOW = 0x4000
|
IN_Q_OVERFLOW = 0x4000
|
||||||
IN_UNMOUNT = 0x2000
|
IN_UNMOUNT = 0x2000
|
||||||
|
IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9
|
||||||
IPPROTO_AH = 0x33
|
IPPROTO_AH = 0x33
|
||||||
IPPROTO_BEETPH = 0x5e
|
IPPROTO_BEETPH = 0x5e
|
||||||
IPPROTO_COMP = 0x6c
|
IPPROTO_COMP = 0x6c
|
||||||
|
@ -1699,6 +1700,27 @@ const (
|
||||||
SPLICE_F_MORE = 0x4
|
SPLICE_F_MORE = 0x4
|
||||||
SPLICE_F_MOVE = 0x1
|
SPLICE_F_MOVE = 0x1
|
||||||
SPLICE_F_NONBLOCK = 0x2
|
SPLICE_F_NONBLOCK = 0x2
|
||||||
|
STATX_ALL = 0xfff
|
||||||
|
STATX_ATIME = 0x20
|
||||||
|
STATX_ATTR_APPEND = 0x20
|
||||||
|
STATX_ATTR_AUTOMOUNT = 0x1000
|
||||||
|
STATX_ATTR_COMPRESSED = 0x4
|
||||||
|
STATX_ATTR_ENCRYPTED = 0x800
|
||||||
|
STATX_ATTR_IMMUTABLE = 0x10
|
||||||
|
STATX_ATTR_NODUMP = 0x40
|
||||||
|
STATX_BASIC_STATS = 0x7ff
|
||||||
|
STATX_BLOCKS = 0x400
|
||||||
|
STATX_BTIME = 0x800
|
||||||
|
STATX_CTIME = 0x80
|
||||||
|
STATX_GID = 0x10
|
||||||
|
STATX_INO = 0x100
|
||||||
|
STATX_MODE = 0x2
|
||||||
|
STATX_MTIME = 0x40
|
||||||
|
STATX_NLINK = 0x4
|
||||||
|
STATX_SIZE = 0x200
|
||||||
|
STATX_TYPE = 0x1
|
||||||
|
STATX_UID = 0x8
|
||||||
|
STATX__RESERVED = 0x80000000
|
||||||
S_BLKSIZE = 0x200
|
S_BLKSIZE = 0x200
|
||||||
S_IEXEC = 0x40
|
S_IEXEC = 0x40
|
||||||
S_IFBLK = 0x6000
|
S_IFBLK = 0x6000
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue