...

Source file src/github.com/cilium/ebpf/internal/sys/fd.go

Documentation: github.com/cilium/ebpf/internal/sys

     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  // NewFD wraps a raw fd with a finalizer.
    26  //
    27  // You must not use the raw fd after calling this function, since the underlying
    28  // file descriptor number may change. This is because the BPF UAPI assumes that
    29  // zero is not a valid fd value.
    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  		// Best effort: this is the number most likely to be an invalid file
    56  		// descriptor. It is equal to -1 (on two's complement arches).
    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  	// Always require the fd to be larger than zero: the BPF API treats the value
    84  	// as "no argument provided".
    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