...
1 package sys
2
3 import (
4 "fmt"
5 "math"
6 "os"
7 "runtime"
8 "strconv"
9
10 "github.com/cilium/ebpf/internal/unix"
11 )
12
13 var ErrClosedFd = unix.EBADF
14
15 type FD struct {
16 raw int
17 }
18
19 func newFD(value int) *FD {
20 fd := &FD{value}
21 runtime.SetFinalizer(fd, (*FD).Close)
22 return fd
23 }
24
25
26
27
28
29
30 func NewFD(value int) (*FD, error) {
31 if value < 0 {
32 return nil, fmt.Errorf("invalid fd %d", value)
33 }
34
35 fd := newFD(value)
36 if value != 0 {
37 return fd, nil
38 }
39
40 dup, err := fd.Dup()
41 _ = fd.Close()
42 return dup, err
43 }
44
45 func (fd *FD) String() string {
46 return strconv.FormatInt(int64(fd.raw), 10)
47 }
48
49 func (fd *FD) Int() int {
50 return fd.raw
51 }
52
53 func (fd *FD) Uint() uint32 {
54 if fd.raw < 0 || int64(fd.raw) > math.MaxUint32 {
55
56
57 return math.MaxUint32
58 }
59 return uint32(fd.raw)
60 }
61
62 func (fd *FD) Close() error {
63 if fd.raw < 0 {
64 return nil
65 }
66
67 value := int(fd.raw)
68 fd.raw = -1
69
70 fd.Forget()
71 return unix.Close(value)
72 }
73
74 func (fd *FD) Forget() {
75 runtime.SetFinalizer(fd, nil)
76 }
77
78 func (fd *FD) Dup() (*FD, error) {
79 if fd.raw < 0 {
80 return nil, ErrClosedFd
81 }
82
83
84
85 dup, err := unix.FcntlInt(uintptr(fd.raw), unix.F_DUPFD_CLOEXEC, 1)
86 if err != nil {
87 return nil, fmt.Errorf("can't dup fd: %v", err)
88 }
89
90 return newFD(dup), nil
91 }
92
93 func (fd *FD) File(name string) *os.File {
94 fd.Forget()
95 return os.NewFile(uintptr(fd.raw), name)
96 }
97
View as plain text