| # HG changeset patch |
| # User Victor Stinner <victor.stinner@gmail.com> |
| # Date 1417423044 -3600 |
| # Mon Dec 01 09:37:24 2014 +0100 |
| # Node ID eba1a6dba205559d724d32c80d955a65e078505e |
| # Parent e6fef4231a8a28ef91c1feaf3bfbcbd29822c939 |
| Issue #17: syscall parser now supports O_CLOEXEC and SOCK_CLOEXEC, fix unit |
| tests on Python 3.4 and newer |
| |
| diff --git a/doc/changelog.rst b/doc/changelog.rst |
| --- a/doc/changelog.rst |
| +++ b/doc/changelog.rst |
| @@ -3,6 +3,12 @@ |
| Changelog |
| ========= |
| |
| +python-ptrace 0.8.2 |
| +------------------- |
| + |
| +* Issue #17: syscall parser now supports O_CLOEXEC and SOCK_CLOEXEC, fix unit |
| + tests on Python 3.4 and newer |
| + |
| python-ptrace 0.8.1 (2014-10-30) |
| -------------------------------- |
| |
| diff --git a/ptrace/syscall/posix_arg.py b/ptrace/syscall/posix_arg.py |
| --- a/ptrace/syscall/posix_arg.py |
| +++ b/ptrace/syscall/posix_arg.py |
| @@ -24,7 +24,7 @@ |
| return formatBits(argument.value, ACCESS_MODE_BITMASK, "F_OK") |
| |
| # From /usr/include/bits/fcntl.h (Ubuntu Feisty, i386) |
| -OPEN_MODE_BITMASK = ( |
| +OPEN_MODE_BITMASK = [ |
| (0o1, "O_WRONLY"), |
| (0o2, "O_RDWR"), |
| (0o100, "O_CREAT"), |
| @@ -40,10 +40,17 @@ |
| (0o200000, "O_DIRECTORY"), |
| (0o400000, "O_NOFOLLOW"), |
| (0o1000000, "O_NOATIME"), |
| -) |
| +] |
| +O_CLOEXEC = 0o02000000 |
| |
| def formatOpenMode(argument): |
| - return formatBits(int(argument.value), OPEN_MODE_BITMASK, "O_RDONLY", oct) |
| + value = argument.value |
| + cloexec = bool(value & O_CLOEXEC) |
| + value = value & ~O_CLOEXEC |
| + text = formatBits(int(value), OPEN_MODE_BITMASK, "O_RDONLY", oct) |
| + if cloexec: |
| + text += '|O_CLOEXEC' |
| + return text |
| |
| CLONE_FLAGS_BITMASK = ( |
| (0x00000100, "CLONE_VM"), |
| diff --git a/ptrace/syscall/posix_constants.py b/ptrace/syscall/posix_constants.py |
| --- a/ptrace/syscall/posix_constants.py |
| +++ b/ptrace/syscall/posix_constants.py |
| @@ -1,5 +1,5 @@ |
| from ptrace.syscall.socketcall_constants import ( |
| - SOCKET_FAMILY, SOCKET_TYPE, SOCKET_PROTOCOL, |
| + SOCKET_FAMILY, SOCKET_PROTOCOL, |
| SETSOCKOPT_LEVEL, SETSOCKOPT_OPTNAME) |
| |
| SYSCALL_ARG_DICT = { |
| @@ -51,7 +51,6 @@ |
| }, |
| "socket": { |
| "domain": SOCKET_FAMILY, |
| - "type": SOCKET_TYPE, |
| "protocol": SOCKET_PROTOCOL, |
| }, |
| "getsockopt": { |
| diff --git a/ptrace/syscall/socketcall_constants.py b/ptrace/syscall/socketcall_constants.py |
| --- a/ptrace/syscall/socketcall_constants.py |
| +++ b/ptrace/syscall/socketcall_constants.py |
| @@ -1,3 +1,5 @@ |
| +import socket |
| + |
| SOCKETCALL = { |
| 1: "socket", |
| 2: "bind", |
| @@ -56,6 +58,19 @@ |
| 10: "SOCK_PACKET", |
| } |
| |
| +def formatSocketType(argument): |
| + value = argument.value |
| + text = [] |
| + if hasattr(socket, 'SOCK_CLOEXEC'): |
| + cloexec = value & socket.SOCK_CLOEXEC |
| + value &= ~socket.SOCK_CLOEXEC |
| + else: |
| + cloexec = False |
| + text = SOCKET_TYPE.get(value, value) |
| + if cloexec: |
| + text += '|SOCK_CLOEXEC' |
| + return text |
| + |
| SOCKET_PROTOCOL = { |
| 1: "IPPROTO_ICMP", |
| 58: "IPPROTO_ICMPV6", |
| diff --git a/ptrace/syscall/syscall_argument.py b/ptrace/syscall/syscall_argument.py |
| --- a/ptrace/syscall/syscall_argument.py |
| +++ b/ptrace/syscall/syscall_argument.py |
| @@ -22,6 +22,7 @@ |
| from ptrace.syscall.freebsd_constants import SYSCALL_ARG_DICT |
| else: |
| SYSCALL_ARG_DICT = {} |
| +from ptrace.syscall.socketcall_constants import formatSocketType |
| |
| KNOWN_STRUCTS = [] |
| if RUNNING_LINUX: |
| @@ -35,6 +36,7 @@ |
| "mmap": {"prot": formatMmapProt}, |
| "mmap2": {"prot": formatMmapProt}, |
| "clone": {"flags": formatCloneFlags}, |
| + "socket": {"type": formatSocketType}, |
| "setsockopt": {"optval": formatOptVal}, |
| } |
| |
| diff --git a/tests/test_strace.py b/tests/test_strace.py |
| --- a/tests/test_strace.py |
| +++ b/tests/test_strace.py |
| @@ -39,10 +39,19 @@ |
| expected = os.fsencode(expected) |
| self.assertEqual(match.group(1), expected) |
| |
| + def test_open(self): |
| + if PY3: |
| + code = 'open(%a).close()' % __file__ |
| + else: |
| + code = 'open(%r).close()' % __file__ |
| + stdout = self.strace(sys.executable, '-c', code) |
| + pattern = re.compile(br"^open\(.*test_strace\.py', O_RDONLY(\|O_CLOEXEC)?\)", re.MULTILINE) |
| + self.assertTrue(pattern.search(stdout), stdout) |
| + |
| def test_socket(self): |
| code = 'import socket; socket.socket(socket.AF_INET, socket.SOCK_STREAM).close()' |
| stdout = self.strace(sys.executable, '-c', code) |
| - pattern = re.compile(b'^socket\\(AF_INET, SOCK_STREAM, ', re.MULTILINE) |
| + pattern = re.compile(br'^socket\(AF_INET, SOCK_STREAM(\|SOCK_CLOEXEC)?, ', re.MULTILINE) |
| self.assertTrue(pattern.search(stdout), stdout) |
| |
| if __name__ == "__main__": |