1
1
#!/usr/local/bin/python
2
# ------------------------------------------------------------------
3
3
# Copyright (c) 2008, Thomas Hurst <tom@hur.st>
5
5
# Use of this file is unrestricted provided this notice is retained.
6
6
# If you use it, it'd be nice if you dropped me a note. Also beer.
7
# ------------------------------------------------------------------
9
# freebsd.get_process_cwd(pid):
10
# Use sysctl() to retrieve the cwd of an arbitrary process on FreeBSD
11
# using kern.proc.filedesc, as used by procstat(1).
12
# Tested on FreeBSD 7-STABLE/amd64 from April 11 2008.
9
freebsd.get_process_cwd(pid):
10
Use sysctl() to retrieve the cwd of an arbitrary process on FreeBSD
11
using kern.proc.filedesc, as used by procstat(1).
12
Tested on FreeBSD 7-STABLE/amd64 from April 11 2008.
14
15
from ctypes import *
16
# This is padded awkwardly, see /usr/include/sys/socket.h
17
17
class sockaddr_storage(Structure):
18
"""struct sockaddr_storage, defined in /usr/include/sys/socket.h"""
19
20
('ss_len', c_char),
20
21
('ss_family', c_char), # /usr/include/sys/_types.h; _uint8_t
24
25
# sizeof(ss_pad1) - sizeof(int64))
27
# struct kinfo_file, defined in /usr/include/sys/user.h
28
28
class kinfo_file(Structure):
29
"""struct kinfo_file, defined in /usr/include/sys/user.h """
30
31
('kf_structsize', c_int),
31
32
('kf_type', c_int),
33
34
('kf_ref_count', c_int),
34
35
('kf_flags', c_int),
35
('kf_offset', c_long), # this is a off_t, a pointer
36
('kf_offset', c_size_t), # this is a off_t, a pointer
36
37
('kf_vnode_type', c_int),
37
38
('kf_sock_domain', c_int),
38
39
('kf_sock_type', c_int),
45
46
libc = CDLL('libc.so')
47
len = c_uint(sizeof(c_uint))
48
uintlen = c_size_t(sizeof(c_uint))
50
if (libc.sysctlbyname('kern.osreldate', byref(ver), byref(len), None, 0) < 0):
51
if (libc.sysctlbyname('kern.osreldate', byref(ver), byref(uintlen), None, 0) < 0):
51
52
raise OSError, "sysctlbyname returned < 0"
53
54
# kern.proc.filedesc added for procstat(1) after these __FreeBSD_versions
54
55
if ver.value < 700104 and ver.value < 800019:
55
56
raise NotImplementedError, "cwd detection requires a recent 7.0-STABLE or 8-CURRENT"
57
59
def get_process_cwd(pid):
60
"""Return string containing the current working directory of the given pid,
61
or None on failure."""
58
62
# /usr/include/sys/sysctl.h
59
63
# CTL_KERN, KERN_PROC, KERN_PROC_FILEDESC
60
64
oid = (c_uint * 4)(1, 14, 14, pid)
62
if libc.sysctl(oid, 4, None, byref(len), None, 0) < 0:
66
if libc.sysctl(oid, 4, None, byref(uintlen), None, 0) < 0:
65
buf = c_char_p(" " * len.value)
66
if libc.sysctl(oid, 4, buf, byref(len), None, 0) < 0:
69
buf = c_char_p(" " * uintlen.value)
70
if libc.sysctl(oid, 4, buf, byref(uintlen), None, 0) < 0:
69
73
kifs = cast(buf, POINTER(kinfo_file))
70
for i in xrange(0, len.value / sizeof(kinfo_file)):
74
for i in xrange(0, uintlen.value / sizeof(kinfo_file)):
72
76
if kif.kf_fd == -1: # KF_FD_TYPE_CWD
75
80
if __name__ == '__main__':
77
82
print " => %d cwd = %s" % (os.getpid(), get_process_cwd(os.getpid()))