You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: raw_tracepoint.go
    path of file: ./repos/hubble-ui/backend/vendor/github.com/cilium/ebpf/link
    
    the code of the file until where you have to start completion: package link

import (
	"errors"
	"fmt"

	"github.com/cilium/ebpf"
	"github.com/cilium/ebpf/internal/sys"
)

type RawTracepointOptions struct {
	// Tracepoint name.
	Name string
	// Program must be of type RawTracepoint*
	Program *ebpf.Program
}

// AttachRawTracepoint links a BPF program to a raw_tracepoint.
//
// Requires at least Linux 4.17.
func AttachRawTracepoint(opts RawTracepointOptions) (Link, error) {
	if t := opts.Program.Type(); t != ebpf.RawTracepoint && t != ebpf.RawTracepointWritable {
		ret
    
func AttachRawTracepoint(opts RawTracepointOptions) (Link, error) {
	if t := opts.Program.Type(); t != ebpf.RawTracepoint && t != ebpf.RawTracepointWritable {
		return nil, fmt.Errorf("invalid program type %s, expected RawTracepoint(Writable)", t)
	}
	if opts.Program.FD() < 0 {
		return nil, fmt.Errorf("invalid program: %w", sys.ErrClosedFd)
	}

	fd, err := sys.RawTracepointOpen(&sys.RawTracepointOpenAttr{
		Name:   sys.NewStringPointer(opts.Name),
		ProgFd: uint32(opts.Program.FD()),
	})
	if err != nil {
		return nil, err
	}

	err = haveBPFLink()
	if errors.Is(err, ErrNotSupported) {
		// Prior to commit 70ed506c3bbc ("bpf: Introduce pinnable bpf_link abstraction")
		// raw_tracepoints are just a plain fd.
		return &simpleRawTracepoint{fd}, nil
	}

	if err != nil {
		return nil, err
	}

	return &rawTracepoint{RawLink{fd: fd}}, nil
}