summaryrefslogtreecommitdiff
path: root/vendor/github.com/cilium/ebpf/internal/sys/fd.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/cilium/ebpf/internal/sys/fd.go')
-rw-r--r--vendor/github.com/cilium/ebpf/internal/sys/fd.go96
1 files changed, 96 insertions, 0 deletions
diff --git a/vendor/github.com/cilium/ebpf/internal/sys/fd.go b/vendor/github.com/cilium/ebpf/internal/sys/fd.go
new file mode 100644
index 000000000..65517d45e
--- /dev/null
+++ b/vendor/github.com/cilium/ebpf/internal/sys/fd.go
@@ -0,0 +1,96 @@
+package sys
+
+import (
+ "fmt"
+ "math"
+ "os"
+ "runtime"
+ "strconv"
+
+ "github.com/cilium/ebpf/internal/unix"
+)
+
+var ErrClosedFd = unix.EBADF
+
+type FD struct {
+ raw int
+}
+
+func newFD(value int) *FD {
+ fd := &FD{value}
+ runtime.SetFinalizer(fd, (*FD).Close)
+ return fd
+}
+
+// NewFD wraps a raw fd with a finalizer.
+//
+// You must not use the raw fd after calling this function, since the underlying
+// file descriptor number may change. This is because the BPF UAPI assumes that
+// zero is not a valid fd value.
+func NewFD(value int) (*FD, error) {
+ if value < 0 {
+ return nil, fmt.Errorf("invalid fd %d", value)
+ }
+
+ fd := newFD(value)
+ if value != 0 {
+ return fd, nil
+ }
+
+ dup, err := fd.Dup()
+ _ = fd.Close()
+ return dup, err
+}
+
+func (fd *FD) String() string {
+ return strconv.FormatInt(int64(fd.raw), 10)
+}
+
+func (fd *FD) Int() int {
+ return fd.raw
+}
+
+func (fd *FD) Uint() uint32 {
+ if fd.raw < 0 || int64(fd.raw) > math.MaxUint32 {
+ // Best effort: this is the number most likely to be an invalid file
+ // descriptor. It is equal to -1 (on two's complement arches).
+ return math.MaxUint32
+ }
+ return uint32(fd.raw)
+}
+
+func (fd *FD) Close() error {
+ if fd.raw < 0 {
+ return nil
+ }
+
+ value := int(fd.raw)
+ fd.raw = -1
+
+ fd.Forget()
+ return unix.Close(value)
+}
+
+func (fd *FD) Forget() {
+ runtime.SetFinalizer(fd, nil)
+}
+
+func (fd *FD) Dup() (*FD, error) {
+ if fd.raw < 0 {
+ return nil, ErrClosedFd
+ }
+
+ // Always require the fd to be larger than zero: the BPF API treats the value
+ // as "no argument provided".
+ dup, err := unix.FcntlInt(uintptr(fd.raw), unix.F_DUPFD_CLOEXEC, 1)
+ if err != nil {
+ return nil, fmt.Errorf("can't dup fd: %v", err)
+ }
+
+ return newFD(dup), nil
+}
+
+func (fd *FD) File(name string) *os.File {
+ fd.Forget()
+ return os.NewFile(uintptr(fd.raw), name)
+}