...
1 package internal
2
3 import (
4 "errors"
5 "fmt"
6 "os"
7 "path/filepath"
8 "runtime"
9 "unsafe"
10
11 "github.com/cilium/ebpf/internal/sys"
12 "github.com/cilium/ebpf/internal/unix"
13 )
14
15 func Pin(currentPath, newPath string, fd *sys.FD) error {
16 const bpfFSType = 0xcafe4a11
17
18 if newPath == "" {
19 return errors.New("given pinning path cannot be empty")
20 }
21 if currentPath == newPath {
22 return nil
23 }
24
25 var statfs unix.Statfs_t
26 if err := unix.Statfs(filepath.Dir(newPath), &statfs); err != nil {
27 return err
28 }
29
30 fsType := int64(statfs.Type)
31 if unsafe.Sizeof(statfs.Type) == 4 {
32
33
34
35 fsType = int64(uint32(statfs.Type))
36 }
37
38 if fsType != bpfFSType {
39 return fmt.Errorf("%s is not on a bpf filesystem", newPath)
40 }
41
42 defer runtime.KeepAlive(fd)
43
44 if currentPath == "" {
45 return sys.ObjPin(&sys.ObjPinAttr{
46 Pathname: sys.NewStringPointer(newPath),
47 BpfFd: fd.Uint(),
48 })
49 }
50
51
52
53 err := unix.Renameat2(unix.AT_FDCWD, currentPath, unix.AT_FDCWD, newPath, unix.RENAME_NOREPLACE)
54 if err == nil {
55
56 return nil
57 }
58 if !os.IsNotExist(err) {
59 return fmt.Errorf("unable to move pinned object to new path %v: %w", newPath, err)
60 }
61
62 return sys.ObjPin(&sys.ObjPinAttr{
63 Pathname: sys.NewStringPointer(newPath),
64 BpfFd: fd.Uint(),
65 })
66 }
67
68 func Unpin(pinnedPath string) error {
69 if pinnedPath == "" {
70 return nil
71 }
72 err := os.Remove(pinnedPath)
73 if err == nil || os.IsNotExist(err) {
74 return nil
75 }
76 return err
77 }
78
View as plain text