Skip to content

Commit 9352782

Browse files
committed
Add fdscan() method to ClamdUnixSocket
1 parent 5c5e33b commit 9352782

File tree

1 file changed

+41
-1
lines changed

1 file changed

+41
-1
lines changed

Diff for: src/clamd/__init__.py

+41-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
import contextlib
1717
import re
1818
import base64
19+
# _multiprocessing.sendfd() only exists in python2
20+
if sys.version_info[0] < 3:
21+
import _multiprocessing
22+
else:
23+
import array
1924

2025
scan_response = re.compile(r"^(?P<path>.*): ((?P<virus>.+) )?(?P<status>(FOUND|OK|ERROR))$")
2126
EICAR = base64.b64decode(
@@ -264,7 +269,7 @@ def _close_socket(self):
264269

265270
def _parse_response(self, msg):
266271
"""
267-
parses responses for SCAN, CONTSCAN, MULTISCAN and STREAM commands.
272+
parses responses for SCAN, CONTSCAN, MULTISCAN, FILDES and STREAM commands.
268273
"""
269274
try:
270275
return scan_response.match(msg).group("path", "virus", "status")
@@ -287,6 +292,25 @@ class initialisation
287292
self.unix_socket = path
288293
self.timeout = timeout
289294

295+
# only works for python >= 3.3
296+
def _send_fd_via_socket_sendmsg(self, fd):
297+
"""
298+
internal use only
299+
"""
300+
return self.clamd_socket.sendmsg([b'\0'], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, array.array("i", [fd]))])
301+
302+
# _multiprocessing.sendfd() only exists in python2
303+
def _send_fd_via_mp_sendfd(self, fd):
304+
"""
305+
internal use only
306+
"""
307+
return _multiprocessing.sendfd(self.clamd_socket.fileno(), fd)
308+
309+
# make _send_fd refer to one of the two _send_fd_* methods above. Either
310+
# _send_fd_via_socket_sendmsg or _send_fd_via_mp_sendfd, depending upon the version of python
311+
"""internal use only"""
312+
_send_fd = _send_fd_via_socket_sendmsg if sys.version_info[0] >= 3 else _send_fd_via_mp_sendfd
313+
290314
def _init_socket(self):
291315
"""
292316
internal use only
@@ -313,3 +337,19 @@ def _error_message(self, exception):
313337
path=self.unix_socket,
314338
msg=exception.args[1]
315339
)
340+
341+
def fdscan(self, path, fd):
342+
"""
343+
Scan a file referenced by a file descriptor.
344+
path (string) : path of file to use for result dictionary (otherwise unused)
345+
fd (int) : file descriptor number (fileno) of file to scan
346+
"""
347+
try:
348+
self._init_socket()
349+
cmd = 'nFILDES\n'.encode('utf-8')
350+
self.clamd_socket.send(cmd)
351+
self._send_fd(fd)
352+
_, reason, status = self._parse_response(self._recv_response_multiline())
353+
return {path: (status, reason)}
354+
finally:
355+
self._close_socket()

0 commit comments

Comments
 (0)