(p *process.Process)
| 87 | } |
| 88 | |
| 89 | func (e *Engine) importInodes(p *process.Process) error { |
| 90 | dirfd, err := unix.Open(fmt.Sprintf("/proc/%d/fd/", p.PID), unix.O_RDONLY, 0o700) |
| 91 | if err != nil { |
| 92 | return fmt.Errorf("open dir: %w", err) |
| 93 | } |
| 94 | defer unix.Close(dirfd) |
| 95 | |
| 96 | count := 0 |
| 97 | for buf := make([]byte, 4096, 4096); ; { |
| 98 | n, _, errno := unix.Syscall(unix.SYS_GETDENTS64, uintptr(dirfd), uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf))) |
| 99 | if errno != 0 { |
| 100 | return fmt.Errorf("getdents64: %w", errno) |
| 101 | } |
| 102 | if n == 0 { |
| 103 | break |
| 104 | } |
| 105 | |
| 106 | for offset := 0; offset < int(n); { |
| 107 | dirent := (*unix.Dirent)(unsafe.Pointer(&buf[offset])) |
| 108 | offset += int(dirent.Reclen) |
| 109 | |
| 110 | if dirent.Type != unix.DT_LNK { |
| 111 | continue |
| 112 | } |
| 113 | |
| 114 | var stat unix.Stat_t |
| 115 | if errno := fstatat(dirfd, dirent, &stat); errno != 0 { |
| 116 | return fmt.Errorf("fstatat: %w", errno) |
| 117 | } |
| 118 | |
| 119 | if stat.Mode&unix.S_IFMT != unix.S_IFSOCK { |
| 120 | continue |
| 121 | } |
| 122 | |
| 123 | inode, ok := e.itab.Get(stat.Ino) |
| 124 | if !ok { |
| 125 | continue |
| 126 | } |
| 127 | |
| 128 | targetFD, valid := 0, true |
| 129 | for i := 0; i < len(dirent.Name); i++ { |
| 130 | if dirent.Name[i] == '\x00' { |
| 131 | break |
| 132 | } |
| 133 | |
| 134 | if !(dirent.Name[i] >= '0' && dirent.Name[i] <= '9') { |
| 135 | valid = false |
| 136 | break |
| 137 | } |
| 138 | |
| 139 | targetFD *= 10 |
| 140 | targetFD += int(dirent.Name[i] - '0') |
| 141 | } |
| 142 | if !valid { |
| 143 | continue |
| 144 | } |
| 145 | |
| 146 | if err := p.ImportInode(targetFD, inode); err != nil { |
no test coverage detected