gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

fd.go (1782B)


      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 }