1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- package internal
- import (
- "errors"
- "fmt"
- "os"
- "path/filepath"
- "runtime"
- "unsafe"
- "github.com/cilium/ebpf/internal/sys"
- "github.com/cilium/ebpf/internal/unix"
- )
- func Pin(currentPath, newPath string, fd *sys.FD) error {
- const bpfFSType = 0xcafe4a11
- if newPath == "" {
- return errors.New("given pinning path cannot be empty")
- }
- if currentPath == newPath {
- return nil
- }
- var statfs unix.Statfs_t
- if err := unix.Statfs(filepath.Dir(newPath), &statfs); err != nil {
- return err
- }
- fsType := int64(statfs.Type)
- if unsafe.Sizeof(statfs.Type) == 4 {
- // We're on a 32 bit arch, where statfs.Type is int32. bpfFSType is a
- // negative number when interpreted as int32 so we need to cast via
- // uint32 to avoid sign extension.
- fsType = int64(uint32(statfs.Type))
- }
- if fsType != bpfFSType {
- return fmt.Errorf("%s is not on a bpf filesystem", newPath)
- }
- defer runtime.KeepAlive(fd)
- if currentPath == "" {
- return sys.ObjPin(&sys.ObjPinAttr{
- Pathname: sys.NewStringPointer(newPath),
- BpfFd: fd.Uint(),
- })
- }
- // Renameat2 is used instead of os.Rename to disallow the new path replacing
- // an existing path.
- err := unix.Renameat2(unix.AT_FDCWD, currentPath, unix.AT_FDCWD, newPath, unix.RENAME_NOREPLACE)
- if err == nil {
- // Object is now moved to the new pinning path.
- return nil
- }
- if !os.IsNotExist(err) {
- return fmt.Errorf("unable to move pinned object to new path %v: %w", newPath, err)
- }
- // Internal state not in sync with the file system so let's fix it.
- return sys.ObjPin(&sys.ObjPinAttr{
- Pathname: sys.NewStringPointer(newPath),
- BpfFd: fd.Uint(),
- })
- }
- func Unpin(pinnedPath string) error {
- if pinnedPath == "" {
- return nil
- }
- err := os.Remove(pinnedPath)
- if err == nil || os.IsNotExist(err) {
- return nil
- }
- return err
- }
|