Skip to content

Instantly share code, notes, and snippets.

@amomchilov
Created April 17, 2024 19:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amomchilov/661ea7fd85f1d60292ebaafce263293f to your computer and use it in GitHub Desktop.
Save amomchilov/661ea7fd85f1d60292ebaafce263293f to your computer and use it in GitHub Desktop.
List open file descriptors for a process using LibProc's `proc_pidinfo` and `PROC_PIDLISTFDS`.
import Darwin
struct ProcFileDescriptorInfo {
let fd: Int32
let path: String
}
func getFileDescriptors(pid: pid_t) -> [ProcFileDescriptorInfo] {
let bufferSize = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, nil, 0)
if bufferSize < 0 {
print("Error: Failed to get file descriptors")
return []
}
let stride = MemoryLayout<proc_fdinfo>.stride
let allFDs = Array<proc_fdinfo>(
unsafeUninitializedCapacity: Int(bufferSize) / stride
) { buffer, initializedCount in
let initialzedByteCount = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, buffer.baseAddress!, bufferSize)
assert(Int(initialzedByteCount).isMultiple(of: stride))
initializedCount = Int(initialzedByteCount) / stride
print("count: \(initializedCount) / \(Int(bufferSize) / stride) entries")
print("size: \(initialzedByteCount) / \(bufferSize) bytes")
}
return allFDs.compactMap { fdinfo -> ProcFileDescriptorInfo? in
let fd = fdinfo.proc_fd
let type = fdinfo.proc_fdtype
switch Int32(type) {
case PROX_FDTYPE_VNODE:
var vnodeInfo = vnode_fdinfowithpath()
let vnodeInfoSize = UInt32(MemoryLayout<vnode_fdinfowithpath>.size)
let ret = proc_pidfdinfo(pid, fd, PROC_PIDFDVNODEPATHINFO, &vnodeInfo, Int32(vnodeInfoSize))
if ret <= 0 {
print("Error: Failed to retrieve vnode info for file descriptor \(fd) of PID \(pid)")
return nil
}
let path = withUnsafeBytes(of: &vnodeInfo.pvip.vip_path) { rawPtr in
let ptr = rawPtr.baseAddress!.assumingMemoryBound(to: CChar.self)
return String(cString: ptr)
}
return ProcFileDescriptorInfo(fd: fd, path: path)
case PROX_FDTYPE_ATALK:
print("apple talk"); return nil
case PROX_FDTYPE_SOCKET:
print("socket"); return nil
case PROX_FDTYPE_PSHM:
print("pshm"); return nil
case PROX_FDTYPE_PSEM:
print("psem"); return nil
case PROX_FDTYPE_KQUEUE:
print("kqueue"); return nil
case PROX_FDTYPE_PIPE:
print("pipe"); return nil
case PROX_FDTYPE_FSEVENTS:
print("fsevents"); return nil
case PROX_FDTYPE_NETPOLICY:
print("netpolicy"); return nil
case PROX_FDTYPE_CHANNEL:
print("channel"); return nil
case PROX_FDTYPE_NEXUS:
print("nexus"); return nil
default:
print("unkonwn \(type)"); return nil
}
}
}
for info in getFileDescriptors(pid: 1597) {
print(info.fd, info.path)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment