You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
67 lines
2.2 KiB
67 lines
2.2 KiB
# -*- coding: utf-8 -
|
|
#
|
|
# This file is part of gunicorn released under the MIT license.
|
|
# See the NOTICE for more information.
|
|
|
|
import errno
|
|
import os
|
|
import sys
|
|
|
|
try:
|
|
import ctypes
|
|
import ctypes.util
|
|
except MemoryError:
|
|
# selinux execmem denial
|
|
# https://bugzilla.redhat.com/show_bug.cgi?id=488396
|
|
raise ImportError
|
|
|
|
SUPPORTED_PLATFORMS = (
|
|
'darwin',
|
|
'freebsd',
|
|
'dragonfly',
|
|
'linux2')
|
|
|
|
if sys.platform not in SUPPORTED_PLATFORMS:
|
|
raise ImportError("sendfile isn't supported on this platform")
|
|
|
|
_libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True)
|
|
_sendfile = _libc.sendfile
|
|
|
|
|
|
def sendfile(fdout, fdin, offset, nbytes):
|
|
if sys.platform == 'darwin':
|
|
_sendfile.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_uint64,
|
|
ctypes.POINTER(ctypes.c_uint64), ctypes.c_voidp,
|
|
ctypes.c_int]
|
|
_nbytes = ctypes.c_uint64(nbytes)
|
|
result = _sendfile(fdin, fdout, offset, _nbytes, None, 0)
|
|
|
|
if result == -1:
|
|
e = ctypes.get_errno()
|
|
if e == errno.EAGAIN and _nbytes.value is not None:
|
|
return _nbytes.value
|
|
raise OSError(e, os.strerror(e))
|
|
return _nbytes.value
|
|
elif sys.platform in ('freebsd', 'dragonfly',):
|
|
_sendfile.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_uint64,
|
|
ctypes.c_uint64, ctypes.c_voidp,
|
|
ctypes.POINTER(ctypes.c_uint64), ctypes.c_int]
|
|
_sbytes = ctypes.c_uint64()
|
|
result = _sendfile(fdin, fdout, offset, nbytes, None, _sbytes, 0)
|
|
if result == -1:
|
|
e = ctypes.get_errno()
|
|
if e == errno.EAGAIN and _sbytes.value is not None:
|
|
return _sbytes.value
|
|
raise OSError(e, os.strerror(e))
|
|
return _sbytes.value
|
|
|
|
else:
|
|
_sendfile.argtypes = [ctypes.c_int, ctypes.c_int,
|
|
ctypes.POINTER(ctypes.c_uint64), ctypes.c_size_t]
|
|
|
|
_offset = ctypes.c_uint64(offset)
|
|
sent = _sendfile(fdout, fdin, _offset, nbytes)
|
|
if sent == -1:
|
|
e = ctypes.get_errno()
|
|
raise OSError(e, os.strerror(e))
|
|
return sent
|
|
|