项目文件夹

文件
wehub-resource-sync 36b3af2e3d
PR Check / Code Quality: Format (push) Failing after 1s
PR Check / Code Quality: Lint (darwin) (push) Failing after 0s
PR Check / Code Quality: Lint (freebsd) (push) Failing after 1s
PR Check / Code Quality: Lint (windows) (push) Failing after 1s
PR Check / Code Quality: Lint (linux) (push) Failing after 1s
PR Check / Security: Vulnerability Scan (push) Failing after 0s
Update Documentation / update-docs (push) Failing after 2s
PR Check / Code Quality: Vendor (push) Failing after 1s
PR Check / Code Quality: Coverage (push) Failing after 0s
PR Check / Tests: Unit (macos-latest) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04-arm) (push) Has been cancelled
PR Check / Tests: Unit (windows-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:22:06 +08:00

107 行
2.5 KiB
Go

//go:build darwin
package proc
import (
"os/exec"
"strconv"
"strings"
"github.com/pranshuparmar/witr/pkg/model"
)
// ListAllOpenFiles uses `lsof` to enumerate open files across all processes.
// Kernel-internal entries (sockets, pipes, kqueue, etc.) are filtered out so
// the result roughly resembles "files a user would recognize on disk". This
// can take a noticeable beat on busy systems.
func ListAllOpenFiles() []*model.LockedFile {
// lsof may exit non-zero when it can't read one of the processes it
// scans (permission denied, process exiting mid-scan, etc.) while still
// emitting valid rows on stdout for the rest; salvage stdout when present.
out, err := exec.Command("lsof", "-l", "-n", "-P").Output()
if err != nil && len(out) == 0 {
return nil
}
var files []*model.LockedFile
for _, line := range strings.Split(string(out), "\n") {
fields := strings.Fields(line)
// COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
if len(fields) < 9 {
continue
}
fdType := fields[4]
if !lsofTypeIsFile(fdType) {
continue
}
pid, err := strconv.Atoi(fields[1])
if err != nil || pid <= 0 {
continue
}
path := strings.Join(fields[8:], " ")
if !isInterestingDarwinPath(path) {
continue
}
files = append(files, &model.LockedFile{
PID: pid,
Process: fields[0],
Path: path,
Type: "OPEN",
Mode: lsofFDMode(fields[3]),
})
}
return files
}
// lsofTypeIsFile keeps regular files and directories; drops sockets, pipes,
// kqueue, character/block devices, and other kernel-internal handle types.
func lsofTypeIsFile(t string) bool {
switch t {
case "REG", "DIR":
return true
}
return false
}
// isInterestingDarwinPath drops paths that are almost never useful when a
// user is asking "who has this file open?".
func isInterestingDarwinPath(p string) bool {
if p == "" || p == "/dev/null" {
return false
}
if strings.HasPrefix(p, "/dev/tty") || strings.HasPrefix(p, "/dev/ttys") {
return false
}
return true
}
// lsofFDMode strips the lock indicators from an lsof FD column and returns
// R/W/RW based on the access mode character. Returns "" if unrecognized.
func lsofFDMode(fd string) string {
if fd == "" {
return ""
}
// Strip trailing lock indicators (W,R,r,w,u,U).
end := len(fd)
for end > 0 {
switch fd[end-1] {
case 'W', 'R', 'r', 'w', 'u', 'U', 'N', ' ':
end--
continue
}
break
}
if end == 0 {
return ""
}
switch fd[end-1] {
case 'r':
return "R"
case 'w':
return "W"
case 'u':
return "RW"
}
return ""
}