/usr/lib/python3/dist-packages/plainbox/vendor/glibc.py is in python3-plainbox 0.25-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 | # encoding: UTF-8
# Copyright (c) 2014 Canonical Ltd.
#
# Author: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
glibc -- things from glibc that have no python interface
========================================================
This package contains ``ctypes`` based wrappers around several missing
functions from glibc. Only missing objects are provided though. Please get the
rest from python's stdlib (aka ``signal``, ``posix`` and ``os``).
.. note::
If you found that a glibc function that you'd like to use, is missing,
please open a bug or provide a patch (it's trivial, just look at existing
functions as an example). All glibc functions are in scope.
"""
from __future__ import absolute_import
from __future__ import division
from ctypes import POINTER
from ctypes import c_int
from ctypes import c_int32
from ctypes import c_long
from ctypes import c_uint
from ctypes import c_uint32
from ctypes import c_uint64
from ctypes import c_uint8
from ctypes import c_ulong
from ctypes import c_voidp
from ctypes import c_size_t
from ctypes import c_ssize_t
from ctypes import get_errno
from errno import EACCES
from errno import EAGAIN
from errno import EBADF
from errno import EBUSY
from errno import EFAULT
from errno import EINTR
from errno import EINVAL
from errno import EIO
from errno import EISDIR
from errno import EMFILE
from errno import ENFILE
from errno import ENODEV
from errno import ENOMEM
from errno import EPERM
from errno import EWOULDBLOCK
import collections
import ctypes
import ctypes.util
import errno
import inspect
import os
import sys
import types
__all__ = [
# NOTE: __all__ in this module is magic!
# This value is extended with types, constants and function from glibc
]
__author__ = 'Zygmunt Krynicki <zygmunt.krynicki@canonical.com>'
__version__ = '0.6.1'
# Load the standard C library on this system
_glibc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True)
_pthread = ctypes.CDLL(ctypes.util.find_library('pthread'))
class LazyModule(types.ModuleType):
"""
A module subclass that imports things lazily on demand.
There are some special provisions to make dir() and __all__ work better so
that pydoc is more informative.
:ivar _lazy:
A mapping of 'name' to 'callable'. The callable is called only once and
defines the lazily loaded version of 'name'.
:ivar _all:
A set of all the "public" objects. This is exposed as the module's
__all__ property. It automatically collects all the objects reported
via :meth:`lazily()` and :meth:`immediate()`.
:ivar _old:
Reference to the old (original) module. This is kept around for python
2.x compatibility. It also seems to help with implementing __dir__()
"""
def __init__(self, name, doc, old):
super(LazyModule, self).__init__(name, doc)
self._lazy = {}
self._all = set()
self._old = old
def __dir__(self):
"""
Lazy-aware version of __dir__()
"""
if sys.version_info[0] == 3:
data = super(LazyModule, self).__dir__()
else:
data = self.__dict__.keys()
data = set(data) | self._all
return sorted(data)
def __getattr__(self, name):
"""
Lazy-aware version of __getattr__()
"""
try:
callable, args = self._lazy[name]
except KeyError:
raise AttributeError(name)
value = callable(*args)
del self._lazy[name]
setattr(self, name, value)
return value
@classmethod
def shadow_normal_module(cls, mod_name=None):
"""
Shadow a module with an instance of LazyModule
:param mod_name:
Name of the module to shadow. By default this is the module that is
making the call into this method. This is not hard-coded as that
module might be called '__main__' if it is executed via 'python -m'
:returns:
A fresh instance of :class:`LazyModule`.
"""
if mod_name is None:
frame = inspect.currentframe()
try:
mod_name = frame.f_back.f_locals['__name__']
finally:
del frame
orig_mod = sys.modules[mod_name]
lazy_mod = cls(orig_mod.__name__, orig_mod.__doc__, orig_mod)
for attr in dir(orig_mod):
setattr(lazy_mod, attr, getattr(orig_mod, attr))
sys.modules[mod_name] = lazy_mod
return lazy_mod
def lazily(self, name, callable, args):
"""
Load something lazily
"""
self._lazy[name] = callable, args
self._all.add(name)
def immediate(self, name, value):
"""
Load something immediately
"""
setattr(self, name, value)
self._all.add(name)
@property
def __all__(self):
"""
A lazy-aware version of __all__
In addition to exposing all of the original module's __all__ it also
contains all the (perhaps not yet loaded) objects defined via
:meth:`lazily()`
"""
return sorted(self._all)
@__all__.setter
def __all__(self, value):
"""
Setter for __all__ that just updates the internal set :ivar:`_all`
This is used by :meth:`shadow_normal_module()` which copies (assigns)
all of the original module's attributes, which also assigns __all__.
"""
self._all.update(value)
# Replace 'glibc' module in sys.modules with LazyModule
_mod = LazyModule.shadow_normal_module()
_glibc_aliasinfo = collections.namedtuple(
'_glibc_aliasinfo', 'py_name c_name ctypes_type c_macros')
_glibc_aliases = [
('time_t', 'time_t', c_long, ('#include <time.h>',)),
('suseconds_t', 'suseconds_t', c_long, ('#include <sys/types.h>',)),
('eventfd_t', 'eventfd_t', c_uint64, ('#include <sys/eventfd.h>',)),
('clockid_t', 'clockid_t', c_int, ('#include <time.h>',)),
]
_glibc_aliases = [_glibc_aliasinfo(*i) for i in _glibc_aliases]
for info in _glibc_aliases:
_mod.immediate(info.py_name, info.ctypes_type)
del info
_glibc_typeinfo = collections.namedtuple(
'_glibc_typeinfo',
'doc py_kind py_name c_name c_packed py_fields c_macros')
# Lazily define all supported glibc types
_glibc_types = [
("""
struct sigset_t;
""",
'struct', 'sigset_t', 'sigset_t', False, (
# There's no spec on that, pulled from glibc
('__val', c_ulong * (1024 // (8 * ctypes.sizeof(c_ulong)))),
), [
'#include <signal.h>'
]),
("""
struct signalfd_siginfo {
uint32_t ssi_signo; /* Signal number */
int32_t ssi_errno; /* Error number (unused) */
int32_t ssi_code; /* Signal code */
uint32_t ssi_pid; /* PID of sender */
uint32_t ssi_uid; /* Real UID of sender */
int32_t ssi_fd; /* File descriptor (SIGIO) */
uint32_t ssi_tid; /* Kernel timer ID (POSIX timers)
uint32_t ssi_band; /* Band event (SIGIO) */
uint32_t ssi_overrun; /* POSIX timer overrun count */
uint32_t ssi_trapno; /* Trap number that caused signal */
int32_t ssi_status; /* Exit status or signal (SIGCHLD) */
int32_t ssi_int; /* Integer sent by sigqueue(3) */
uint64_t ssi_ptr; /* Pointer sent by sigqueue(3) */
uint64_t ssi_utime; /* User CPU time consumed (SIGCHLD) */
uint64_t ssi_stime; /* System CPU time consumed (SIGCHLD) */
uint64_t ssi_addr; /* Address that generated signal
(for hardware-generated signals) */
uint8_t __pad[48]; /* Pad size to 128 bytes (allow for
additional fields in the future) */
};""",
'struct', 'signalfd_siginfo', 'struct signalfd_siginfo', False, (
('ssi_signo', c_uint32),
('ssi_errno', c_int32),
('ssi_code', c_int32),
('ssi_pid', c_uint32),
('ssi_uid', c_uint32),
('ssi_fd', c_int32),
('ssi_tid', c_uint32),
('ssi_band', c_uint32),
('ssi_overrun', c_uint32),
('ssi_trapno', c_uint32),
('ssi_status', c_int32),
('ssi_int', c_int32),
('ssi_ptr', c_uint64),
('ssi_utime', c_uint64),
('ssi_stime', c_uint64),
('ssi_addr', c_uint64),
('__pad', c_uint8 * 48),
), [
'#include <sys/signalfd.h>'
]),
("""
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
""",
'union', 'epoll_data_t', 'epoll_data_t', False, (
('ptr', c_voidp),
('fd', c_int),
('u32', c_uint32),
('u64', c_uint64),
), [
'#include <sys/epoll.h>'
]),
("""
struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
""",
'struct', 'epoll_event', 'struct epoll_event', True, (
('events', c_uint32),
('data', 'glibc.epoll_data_t'),
), [
'#include <sys/epoll.h>'
]),
("""
struct itimerspec {
struct timespec it_interval; /* Interval for periodic timer */
struct timespec it_value; /* Initial expiration */
};
""",
'struct', 'itimerspec', 'struct itimerspec', False, (
('it_interval', 'glibc.timespec'),
('it_value', 'glibc.timespec'),
), [
'#include <time.h>',
]),
("""
struct timespec {
time_t tv_sec; /* Seconds */
long tv_nsec; /* Nanoseconds */
};
""",
'struct', 'timespec', 'struct timespec', False, (
# NOTE: time_t is __TIME_T_TYPE, is __SYSCALL_SLONG_TYPE, is
# __SQUAD_TYPE, is __quad_t or long it. This is likely not
# true on !x86_64 but I have to start somewhere.
#
# offtopic, I really really think the type proliferation in C is
# out of control. What would be the problem with having only two
# types? machine dependent natural word size (same as pointer
# size), fuck that single exotic 36 bit machine, and a portable
# collection of fixed-width signed/unsigned types?
#
# long, long long, quad and everything else is just meaningless
# and makes writing portable software harder as nobody knows how
# to use those types *correctly* and portably to begin with.
('tv_sec', c_long),
('tv_nsec', c_long),
), [
'#include <time.h>',
]),
("""
struct timeval {
time_t tv_sec; /* Seconds */
suseconds_t tv_usec; /* Microseconds */
};
""",
'struct', 'timeval', 'struct timeval', False, (
('tv_sec', 'glibc.time_t'),
('tv_usec', 'glibc.suseconds_t'),
), [
'#include <sys/time.h>',
]),
]
_glibc_types = [_glibc_typeinfo(*i) for i in _glibc_types]
def _glibc_struct_repr(self):
return 'struct {} at {:#x}\n'.format(
self.__class__.__name__, id(self)
) + '\n'.join(
' {}: {!r}'.format(f_name, getattr(self, f_name))
for f_name, f_type in self._fields_
)
def _glibc_type(doc, py_kind, py_name, c_name, c_packed, py_fields, c_macros):
_globals = {'ctypes': ctypes, 'glibc': _mod}
py_fields = tuple([
(py_field_name, (eval(py_field_type, _globals)
if isinstance(py_field_type, str)
else py_field_type))
for py_field_name, py_field_type in py_fields
])
if py_kind == 'struct':
new_type = type(py_name, (ctypes.Structure, ), {
'__doc__': doc,
'_fields_': py_fields,
'_pack_': c_packed,
'__repr__': _glibc_struct_repr,
})
elif py_kind == 'union':
if c_packed:
raise ValueError("c_packed is meaningless for unions")
new_type = type(py_name, (ctypes.Union, ), {
'__doc__': doc,
'_fields_': py_fields,
})
else:
raise ValueError("bad value of py_kind")
return new_type
for info in _glibc_types:
_mod.lazily(info[2], _glibc_type, info)
del info
# del _glibc_types
_glibc_constantinfo = collections.namedtuple(
'_glibc_constantinfo', 'name py_ctype py_value c_macros')
# Non-lazily define all supported glibc constants
_glibc_constants = (
('NSIG', c_int, 65, ('#include <signal.h>',)),
('SIG_BLOCK', c_int, 0, ('#include <signal.h>',)),
('SIG_UNBLOCK', c_int, 1, ('#include <signal.h>',)),
('SIG_SETMASK', c_int, 2, ('#include <signal.h>',)),
('CLD_EXITED', c_int, 1, ('#include <signal.h>',)),
('CLD_KILLED', c_int, 2, ('#include <signal.h>',)),
('CLD_DUMPED', c_int, 3, ('#include <signal.h>',)),
('CLD_TRAPPED', c_int, 4, ('#include <signal.h>',)),
('CLD_STOPPED', c_int, 5, ('#include <signal.h>',)),
('CLD_CONTINUED', c_int, 6, ('#include <signal.h>',)),
('FD_SETSIZE', c_int, 1024, ('#include <sys/types.h>',)),
('SFD_CLOEXEC', c_int, 0o2000000, ('#include <sys/signalfd.h>',)),
('SFD_NONBLOCK', c_int, 0o0004000, ('#include <sys/signalfd.h>',)),
('EPOLL_CLOEXEC', c_int, 0o2000000, ('#include <sys/epoll.h>',)),
# opcodes for epoll_ctl()
('EPOLL_CTL_ADD', c_int, 1, ('#include <sys/epoll.h>',)),
('EPOLL_CTL_DEL', c_int, 2, ('#include <sys/epoll.h>',)),
('EPOLL_CTL_MOD', c_int, 3, ('#include <sys/epoll.h>',)),
# enum EPOLL_EVENTS
('EPOLLIN', c_uint, 0x0001, ('#include <sys/epoll.h>',)),
('EPOLLPRI', c_uint, 0x0002, ('#include <sys/epoll.h>',)),
('EPOLLOUT', c_uint, 0x0004, ('#include <sys/epoll.h>',)),
('EPOLLERR', c_uint, 0x0008, ('#include <sys/epoll.h>',)),
('EPOLLHUP', c_uint, 0x0010, ('#include <sys/epoll.h>',)),
('EPOLLRDNORM', c_uint, 0x0040, ('#include <sys/epoll.h>',)),
('EPOLLRDBAND', c_uint, 0x0080, ('#include <sys/epoll.h>',)),
('EPOLLWRNORM', c_uint, 0x0100, ('#include <sys/epoll.h>',)),
('EPOLLWRBAND', c_uint, 0x0200, ('#include <sys/epoll.h>',)),
('EPOLLMSG', c_uint, 0x0400, ('#include <sys/epoll.h>',)),
('EPOLLRDHUP', c_uint, 0x2000, ('#include <sys/epoll.h>',)),
('EPOLLONESHOT', c_uint, 1 << 30, ('#include <sys/epoll.h>',)),
('EPOLLET', c_uint, 1 << 31, ('#include <sys/epoll.h>',)),
# ...
('O_CLOEXEC', c_int, 0o2000000, (
'#define _POSIX_C_SOURCE 200809L',
'#include <sys/types.h>',
'#include <sys/stat.h>',
'#include <fcntl.h>')),
('O_DIRECT', c_int, 0o0040000, (
'#define _GNU_SOURCE',
'#include <sys/types.h>',
'#include <sys/stat.h>',
'#include <fcntl.h>')),
('O_NONBLOCK', c_int, 0o00004000, (
'#define _POSIX_C_SOURCE 200809L',
'#include <sys/types.h>',
'#include <sys/stat.h>',
'#include <fcntl.h>')),
('PIPE_BUF', c_int, 4096, ('#include <limits.h>',)),
('PR_SET_PDEATHSIG', c_int, 1, ('#include <sys/prctl.h>',)),
('PR_GET_PDEATHSIG', c_int, 2, ('#include <sys/prctl.h>',)),
('PR_GET_DUMPABLE', c_int, 3, ('#include <sys/prctl.h>',)),
('PR_SET_DUMPABLE', c_int, 4, ('#include <sys/prctl.h>',)),
('PR_GET_UNALIGN', c_int, 5, ('#include <sys/prctl.h>',)),
('PR_SET_UNALIGN', c_int, 6, ('#include <sys/prctl.h>',)),
('PR_GET_KEEPCAPS', c_int, 7, ('#include <sys/prctl.h>',)),
('PR_SET_KEEPCAPS', c_int, 8, ('#include <sys/prctl.h>',)),
('PR_GET_FPEMU', c_int, 9, ('#include <sys/prctl.h>',)),
('PR_SET_FPEMU', c_int, 10, ('#include <sys/prctl.h>',)),
('PR_GET_FPEXC', c_int, 11, ('#include <sys/prctl.h>',)),
('PR_SET_FPEXC', c_int, 12, ('#include <sys/prctl.h>',)),
('PR_GET_TIMING', c_int, 13, ('#include <sys/prctl.h>',)),
('PR_SET_TIMING', c_int, 14, ('#include <sys/prctl.h>',)),
('PR_SET_NAME', c_int, 15, ('#include <sys/prctl.h>',)),
('PR_GET_NAME', c_int, 16, ('#include <sys/prctl.h>',)),
('PR_GET_ENDIAN', c_int, 19, ('#include <sys/prctl.h>',)),
('PR_SET_ENDIAN', c_int, 20, ('#include <sys/prctl.h>',)),
('PR_GET_SECCOMP', c_int, 21, ('#include <sys/prctl.h>',)),
('PR_SET_SECCOMP', c_int, 22, ('#include <sys/prctl.h>',)),
('PR_CAPBSET_READ', c_int, 23, ('#include <sys/prctl.h>',)),
('PR_CAPBSET_DROP', c_int, 24, ('#include <sys/prctl.h>',)),
('PR_GET_TSC', c_int, 25, ('#include <sys/prctl.h>',)),
('PR_SET_TSC', c_int, 26, ('#include <sys/prctl.h>',)),
('PR_GET_SECUREBITS', c_int, 27, ('#include <sys/prctl.h>',)),
('PR_SET_SECUREBITS', c_int, 28, ('#include <sys/prctl.h>',)),
('PR_SET_TIMERSLACK', c_int, 29, ('#include <sys/prctl.h>',)),
('PR_GET_TIMERSLACK', c_int, 30, ('#include <sys/prctl.h>',)),
('PR_TASK_PERF_EVENTS_DISABLE', c_int, 31, ('#include <sys/prctl.h>',)),
('PR_TASK_PERF_EVENTS_ENABLE', c_int, 32, ('#include <sys/prctl.h>',)),
('PR_MCE_KILL', c_int, 33, ('#include <sys/prctl.h>',)),
('PR_MCE_KILL_GET', c_int, 34, ('#include <sys/prctl.h>',)),
('PR_SET_MM', c_int, 35, ('#include <sys/prctl.h>',)),
('PR_SET_CHILD_SUBREAPER', c_int, 36, ('#include <sys/prctl.h>',)),
('PR_GET_CHILD_SUBREAPER', c_int, 37, ('#include <sys/prctl.h>',)),
('PR_SET_NO_NEW_PRIVS', c_int, 38, ('#include <sys/prctl.h>',)),
('PR_GET_NO_NEW_PRIVS', c_int, 39, ('#include <sys/prctl.h>',)),
('PR_GET_TID_ADDRESS', c_int, 40, ('#include <sys/prctl.h>',)),
('PR_SET_THP_DISABLE', c_int, 41, ('#include <sys/prctl.h>',)),
('PR_GET_THP_DISABLE', c_int, 42, ('#include <sys/prctl.h>',)),
('PR_UNALIGN_NOPRINT', c_int, 1, ('#include <sys/prctl.h>',)),
('PR_UNALIGN_SIGBUS', c_int, 2, ('#include <sys/prctl.h>',)),
('PR_FPEMU_NOPRINT', c_int, 1, ('#include <sys/prctl.h>',)),
('PR_FPEMU_SIGFPE', c_int, 2, ('#include <sys/prctl.h>',)),
('PR_FP_EXC_SW_ENABLE', c_int, 0x80, ('#include <sys/prctl.h>',)),
('PR_FP_EXC_DIV', c_int, 0x010000, (
'#include <sys/prctl.h>',)),
('PR_FP_EXC_OVF', c_int, 0x020000, (
'#include <sys/prctl.h>',)),
('PR_FP_EXC_UND', c_int, 0x040000, (
'#include <sys/prctl.h>',)),
('PR_FP_EXC_RES', c_int, 0x080000, (
'#include <sys/prctl.h>',)),
('PR_FP_EXC_INV', c_int, 0x100000, (
'#include <sys/prctl.h>',)),
('PR_FP_EXC_DISABLED', c_int, 0, ('#include <sys/prctl.h>',)),
('PR_FP_EXC_NONRECOV', c_int, 1, ('#include <sys/prctl.h>',)),
('PR_FP_EXC_ASYNC', c_int, 2, ('#include <sys/prctl.h>',)),
('PR_FP_EXC_PRECISE', c_int, 3, ('#include <sys/prctl.h>',)),
('PR_TIMING_STATISTICAL', c_int, 0, ('#include <sys/prctl.h>',)),
('PR_TIMING_TIMESTAMP', c_int, 1, ('#include <sys/prctl.h>',)),
('PR_ENDIAN_BIG', c_int, 0, ('#include <sys/prctl.h>',)),
('PR_ENDIAN_LITTLE', c_int, 1, ('#include <sys/prctl.h>',)),
('PR_ENDIAN_PPC_LITTLE', c_int, 2, ('#include <sys/prctl.h>',)),
('PR_TSC_ENABLE', c_int, 1, ('#include <sys/prctl.h>',)),
('PR_TSC_SIGSEGV', c_int, 2, ('#include <sys/prctl.h>',)),
('PR_MCE_KILL_CLEAR', c_int, 0, ('#include <sys/prctl.h>',)),
('PR_MCE_KILL_SET', c_int, 1, ('#include <sys/prctl.h>',)),
('PR_MCE_KILL_LATE', c_int, 0, ('#include <sys/prctl.h>',)),
('PR_MCE_KILL_EARLY', c_int, 1, ('#include <sys/prctl.h>',)),
('PR_MCE_KILL_DEFAULT', c_int, 2, ('#include <sys/prctl.h>',)),
('PR_SET_MM_START_CODE', c_int, 1, ('#include <sys/prctl.h>',)),
('PR_SET_MM_END_CODE', c_int, 2, ('#include <sys/prctl.h>',)),
('PR_SET_MM_START_DATA', c_int, 3, ('#include <sys/prctl.h>',)),
('PR_SET_MM_END_DATA', c_int, 4, ('#include <sys/prctl.h>',)),
('PR_SET_MM_START_STACK', c_int, 5, ('#include <sys/prctl.h>',)),
('PR_SET_MM_START_BRK', c_int, 6, ('#include <sys/prctl.h>',)),
('PR_SET_MM_BRK', c_int, 7, ('#include <sys/prctl.h>',)),
('PR_SET_MM_ARG_START', c_int, 8, ('#include <sys/prctl.h>',)),
('PR_SET_MM_ARG_END', c_int, 9, ('#include <sys/prctl.h>',)),
('PR_SET_MM_ENV_START', c_int, 10, ('#include <sys/prctl.h>',)),
('PR_SET_MM_ENV_END', c_int, 11, ('#include <sys/prctl.h>',)),
('PR_SET_MM_AUXV', c_int, 12, ('#include <sys/prctl.h>',)),
('PR_SET_MM_EXE_FILE', c_int, 13, ('#include <sys/prctl.h>',)),
('PR_SET_PTRACER', c_int, 0x59616d61, (
'#include <sys/prctl.h>',)),
('PR_SET_PTRACER_ANY', c_ulong, -1, ('#include <sys/prctl.h>',)),
('TFD_TIMER_ABSTIME', c_int, 1, ('#include <sys/timerfd.h>',)),
('TFD_CLOEXEC', c_int, 0o2000000, (
'#include <sys/timerfd.h>',)),
('TFD_NONBLOCK', c_int, 0o0004000, (
'#include <sys/timerfd.h>',)),
('EFD_CLOEXEC', c_int, 0o2000000, ('#include <sys/eventfd.h>',)),
('EFD_NONBLOCK', c_int, 0o0004000, ('#include <sys/eventfd.h>',)),
('EFD_SEMAPHORE', c_int, 1, ('#include <sys/eventfd.h>',)),
('CLOCK_REALTIME', c_int, 0, ('#include <time.h>',)),
('CLOCK_MONOTONIC', c_int, 1, ('#include <time.h>',)),
('CLOCK_PROCESS_CPUTIME_ID', c_int, 2, ('#include <time.h>',)),
('CLOCK_THREAD_CPUTIME_ID', c_int, 3, ('#include <time.h>',)),
('CLOCK_MONOTONIC_RAW', c_int, 4, ('#include <time.h>',)),
('CLOCK_REALTIME_COARSE', c_int, 5, ('#include <time.h>',)),
('CLOCK_MONOTONIC_COARSE', c_int, 6, ('#include <time.h>',)),
('CLOCK_BOOTTIME', c_int, 7, ('#include <time.h>',)),
('CLOCK_REALTIME_ALARM', c_int, 8, ('#include <time.h>',)),
('CLOCK_BOOTTIME_ALARM', c_int, 9, ('#include <time.h>',)),
# fcntl(2) codes
('F_SETPIPE_SZ', c_int, 1031, (
'#define _GNU_SOURCE',
'#include <unistd.h>',
'#include <fcntl.h>',)),
('F_GETPIPE_SZ', c_int, 1032, (
'#define _GNU_SOURCE',
'#include <unistd.h>',
'#include <fcntl.h>',)),
)
_glibc_constants = [_glibc_constantinfo(*i) for i in _glibc_constants]
for info in _glibc_constants:
_mod.immediate(info.name, info.py_value)
del info
# del _glibc_constants
# Lazily define all supported glibc functions
_glibc_functions = (
('sigemptyset', c_int, ['ctypes.POINTER(glibc.sigset_t)'],
"""int sigemptyset(sigset_t *set);""",
-1, {
errno.EINVAL: "sig is not a valid signal"
}),
('sigfillset', c_int, ['ctypes.POINTER(glibc.sigset_t)'],
"""int sigfillset(sigset_t *set);""",
-1, {
errno.EINVAL: "sig is not a valid signal"
}),
('sigaddset', c_int, ['ctypes.POINTER(glibc.sigset_t)', c_int],
"""int sigaddset(sigset_t *set, int signum);""",
-1, {
errno.EINVAL: "sig is not a valid signal"
}),
('sigdelset', c_int, ['ctypes.POINTER(glibc.sigset_t)', c_int],
"""int sigdelset(sigset_t *set, int signum);""",
-1, {
errno.EINVAL: "sig is not a valid signal"
}),
('sigismember', c_int, ['ctypes.POINTER(glibc.sigset_t)', c_int],
"""int sigismember(sigset_t *set, int signum);""",
-1, {
errno.EINVAL: "sig is not a valid signal"
}),
('sigprocmask', c_int, [c_int, 'ctypes.POINTER(glibc.sigset_t)',
'ctypes.POINTER(glibc.sigset_t)'],
"""int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);""",
-1, {
errno.EFAULT: ("The ``set`` or ``oldset`` arguments points outside"
" of the process's address space"),
errno.EINVAL: "The value specified in ``how`` was invalid",
}),
('pthread_sigmask', c_int, [c_int, 'ctypes.POINTER(glibc.sigset_t)',
'ctypes.POINTER(glibc.sigset_t)'],
"""int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);"""
'pthread', {
errno.EFAULT: ("The ``set`` or ``oldset`` arguments points outside"
" of the process's address space"),
errno.EINVAL: "The value specified in ``how`` was invalid",
}),
('signalfd', c_int, [c_int, 'ctypes.POINTER(glibc.sigset_t)', c_int],
"""int signalfd(int fd, const sigset_t *mask, int flags);""",
-1, {
errno.EBADF: "The fd file descriptor is not a valid file descriptor",
errno.EINVAL: ("fd is not a valid signalfd file descriptor; "
"flags is invalid; "
"in Linux 2.6.26 or earlier, flags is nonzero"),
errno.EMFILE: ("The per-process limit of open file descriptors has"
" been reached"),
errno.ENFILE: ("The system-wide limit on the total number of open",
" file descriptors has been reached"),
errno.ENODEV: ("Could not mount (internal) anonymous inode device"),
errno.ENOMEM: ("There was insufficient memory to create a new"
" signalfd file descriptor")
}),
('epoll_create', c_int, [c_int],
"""int epoll_create(int size);""",
-1, {
errno.EINVAL: "size is not positive.",
errno.EMFILE: ("The per-user limit on the number of epoll instances"
" imposed by /proc/sys/fs/epoll/max_user_instances was"
" encountered. See epoll(7) for further details."),
errno.ENFILE: ("The system limit on the total number of open files"
" has been reached."),
errno.ENOMEM: ("There was insufficient memory to create the kernel"
" object."),
}),
('epoll_create1', c_int, [c_int],
"""int epoll_create1(int flags);""",
-1, {
errno.EINVAL: "Invalid value specified in flags.",
errno.EMFILE: ("The per-user limit on the number of epoll instances"
" imposed by /proc/sys/fs/epoll/max_user_instances was"
" encountered. See epoll(7) for further details."),
errno.ENFILE: ("The system limit on the total number of open files"
" has been reached."),
errno.ENOMEM: ("There was insufficient memory to create the kernel"
" object."),
}),
('epoll_wait', c_int, [c_int, 'ctypes.POINTER(glibc.epoll_event)', c_int,
c_int],
"""int epoll_wait(int epfd, struct epoll_event *events,
int maxevents, int timeout);""",
-1, {
errno.EBADF: "epfd is not a valid file descriptor.",
errno.EFAULT: ("The memory area pointed to by events is not"
" accessible with write permissions."),
errno.EINTR: ("The call was interrupted by a signal handler before"
" either (1) any of the requested events occurred"
" or (2) the timeout expired; see signal(7)."),
errno.EINVAL: ("epfd is not an epoll file descriptor, or maxevents"
" is less than or equal to zero."),
}),
('epoll_pwait', c_int, [c_int, 'ctypes.POINTER(glibc.epoll_event)', c_int,
c_int, 'ctypes.POINTER(glibc.sigset_t)'],
"""int epoll_pwait(int epfd, struct epoll_event *events,
int maxevents, int timeout,
const sigset_t *sigmask);""",
-1, {
errno.EBADF: "epfd is not a valid file descriptor.",
errno.EFAULT: ("The memory area pointed to by events is not"
" accessible with write permissions."),
errno.EINTR: ("The call was interrupted by a signal handler before"
" either (1) any of the requested events occurred"
" or (2) the timeout expired; see signal(7)."),
errno.EINVAL: ("epfd is not an epoll file descriptor, or maxevents"
" is less than or equal to zero."),
}),
('epoll_ctl', c_int, [c_int, c_int, c_int,
'ctypes.POINTER(glibc.epoll_event)'],
"int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);",
-1, {
errno.EBADF: "epfd or fd is not a valid file descriptor.",
errno.EEXIST: ("op was EPOLL_CTL_ADD, and the supplied file"
" descriptor fd is already registered with this"
" epoll instance."),
errno.EINVAL: ("epfd is not an epoll file descriptor, or fd is the"
" same as epfd, or the requested operation op is not"
" supported by this interface."),
errno.ENOENT: ("op was EPOLL_CTL_MOD or EPOLL_CTL_DEL, and fd is not"
" registered with this epoll instance."),
errno.ENOMEM: ("There was insufficient memory to handle the requested"
" op control operation."),
errno.ENOSPC: ("The limit imposed by"
" /proc/sys/fs/epoll/max_user_watches was encountered"
" while trying to register (EPOLL_CTL_ADD) a new file"
" descriptor on an epoll instance. See epoll(7) for"
" further details."),
errno.EPERM: "The target file fd does not support epoll.",
}),
('pipe', c_int, [POINTER(c_int * 2)],
"""int pipe2(int pipefd[2], int flags);""",
-1, {
errno.EFAULT: "pipefd is not valid.",
errno.EMFILE: "Too many file descriptors are in use by the process.",
errno.ENFILE: ("The system limit on the total number of open files"
" has been reached."),
}),
('pipe2', c_int, [POINTER(c_int * 2), c_int],
"""int pipe2(int pipefd[2], int flags);""",
-1, {
errno.EFAULT: "pipefd is not valid.",
errno.EINVAL: "Invalid value in flags.",
errno.EMFILE: "Too many file descriptors are in use by the process.",
errno.ENFILE: ("The system limit on the total number of open files"
" has been reached."),
}),
('dup', c_int, [c_int],
"""int dup(int oldfd);""",
-1, {
errno.EBADF: ("oldfd isn't an open file descriptor, or newfd is out"
" of the allowed range for file descriptors."),
errno.EMFILE: ("The process already has the maximum number of file"
" descriptors open and tried to open a new one."),
}),
('dup2', c_int, [c_int, c_int],
"""int dup2(int oldfd, int newfd);""",
-1, {
errno.EBADF: ("oldfd isn't an open file descriptor, or newfd is out"
" of the allowed range for file descriptors."),
errno.EBUSY: ("(Linux only) This may be returned by dup2() or dup3()"
" during a race condition with open(2) and dup()."),
errno.EINTR: ("The dup2() or dup3() call was interrupted by a signal;"
" see signal(7)."),
errno.EMFILE: ("The process already has the maximum number of file"
" descriptors open and tried to open a new one."),
}),
('dup3', c_int, [c_int, c_int, c_int],
"""int dup3(int oldfd, int newfd, int flags);""",
-1, {
errno.EBADF: ("oldfd isn't an open file descriptor, or newfd is out"
" of the allowed range for file descriptors."),
errno.EBUSY: ("(Linux only) This may be returned by dup2() or dup3()"
" during a race condition with open(2) and dup()."),
errno.EINTR: ("The dup2() or dup3() call was interrupted by a signal;"
" see signal(7)."),
errno.EINVAL: ("(dup3()) flags contain an invalid value. Or, oldfd"
" was equal to newfd."),
errno.EMFILE: ("The process already has the maximum number of file"
" descriptors open and tried to open a new one."),
}),
('read', c_ssize_t, [c_int, c_voidp, c_size_t],
"""ssize_t read(int fd, void *buf, size_t count);""",
-1, {
EAGAIN: (
"The file descriptor fd refers to a file other than a socket"
" and has been marked nonblocking (O_NONBLOCK), and the read"
" would block."),
EWOULDBLOCK: '\n'.join([(
"The file descriptor fd refers to a file other than a socket"
" and has been marked nonblocking (O_NONBLOCK), and the read"
" would block."
), (
"The file descriptor fd refers to a socket and has been marked"
" nonblocking (O_NONBLOCK), and the read would block."
" POSIX.1-2001 allows either EAGAIN or EWOULDBLOCK error to be"
" returned for this case, and does not require these constants"
" to have the same value, so a portable application should"
" check for both possibilities.")]),
EBADF: (
"fd is not a valid file descriptor or is not open for reading."),
EFAULT: (
"buf is outside your accessible address space."),
EINTR: (
"The call was interrupted by a signal before any data was read;"
" see signal(7)."),
EINVAL: '\n'.join([(
"fd is attached to an object which is unsuitable for reading;"
" or the file was opened with the O_DIRECT flag, and either the"
" address specified in buf, the value specified in count, or"
" the current file offset is not suitably aligned."
), (
"fd was created via a call to timerfd_create(2) and the wrong"
" size buffer was given to read(); see timerfd_create(2) for"
" further information.")]),
EIO: (
"I/O error. This will happen for example when the process is in"
" a background process group, tries to read from its controlling"
" terminal, and either it is ignoring or blocking SIGTTIN or"
" its process group is orphaned. It may also occur when there is"
" a low-level I/O error while reading from a disk or tape."),
EISDIR: (
"fd refers to a directory.")
}),
('close', c_int, [c_int],
"""int close(int fd);""",
-1, {
errno.EBADF: "fd isn't a valid open file descriptor.",
errno.EINTR: ("The close() call was interrupted by a signal;"
" see signal(7)."),
errno.EIO: "An I/O error occurred."
}),
('prctl', c_int, [c_int, c_ulong, c_ulong, c_ulong, c_ulong],
"""int prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5);""",
-1, {
EFAULT: "arg2 is an invalid address.",
EINVAL: '\n'.join([
("The value of option is not recognized."),
("option is PR_MCE_KILL or PR_MCE_KILL_GET or PR_SET_MM,"
" and unused prctl() arguments were not specified as zero."),
("arg2 is not valid value for this option."),
("option is PR_SET_SECCOMP or PR_GET_SECCOMP, and the kernel"
" was not configured with CONFIG_SECCOMP."),
("option is PR_SET_MM, and one of the following is true:\n"
" * arg4 or arg5 is nonzero;\n"
" * arg3 is greater than TASK_SIZE (the limit on the size\n"
" of the user address space for this architecture);\n"
" * arg2 is PR_SET_MM_START_CODE, PR_SET_MM_END_CODE,\n"
" PR_SET_MM_START_DATA, PR_SET_MM_END_DATA,\n"
" or PR_SET_MM_START_STACK, and the permissions\n"
" of the corresponding memory area are not as required;\n"
" * arg2 is PR_SET_MM_START_BRK or PR_SET_MM_BRK, and arg3\n"
" is less than or equal to the end of the data segment\n"
" or specifies a value that would cause the RLIMIT_DATA\n"
" resource limit to be exceeded."),
("option is PR_SET_PTRACER and arg2 is not 0,"
" PR_SET_PTRACER_ANY, or the PID of an existing process."),
("option is PR_SET_PDEATHSIG and arg2 is not a valid signal"
" number."),
("option is PR_SET_DUMPABLE and arg2 is neither"
" SUID_DUMP_DISABLE nor SUID_DUMP_USER.\n"),
("option is PR_SET_TIMING and arg2 is not"
" PR_TIMING_STATISTICAL."),
("option is PR_SET_NO_NEW_PRIVS and arg2 is not equal to 1"
" or arg3, arg4, or arg5 is nonzero."),
("option is PR_GET_NO_NEW_PRIVS and arg2, arg3, arg4,"
" or arg5 is nonzero."),
("option is PR_SET_THP_DISABLE and arg3, arg4,"
" or arg5 is nonzero."),
("option is PR_GET_THP_DISABLE and arg2, arg3, arg4,"
" or arg5 is nonzero.")
]),
EPERM: '\n'.join([
("option is PR_SET_SECUREBITS, and the caller does not have the"
" CAP_SETPCAP capability, or tried to unset a \"locked\" flag,"
" or tried to set a flag whose corresponding locked flag was"
" set (see capabilities(7))."),
("option is PR_SET_KEEPCAPS, and the callers's"
" SECURE_KEEP_CAPS_LOCKED flag is set (see capabilities(7))."),
("option is PR_CAPBSET_DROP, and the caller does not have"
" the CAP_SETPCAP capability."),
("option is PR_SET_MM, and the caller does not have"
" the CAP_SYS_RESOURCE capability.")
]),
EACCES: ("option is PR_SET_MM, and arg3 is PR_SET_MM_EXE_FILE,"
" the file is not executable."),
EBUSY: ("option is PR_SET_MM, arg3 is PR_SET_MM_EXE_FILE, and this"
" the second attempt to change the /proc/pid/exe symbolic"
" link, which is prohibited."),
EBADF: ("option is PR_SET_MM, arg3 is PR_SET_MM_EXE_FILE,"
" and the file descriptor passed in arg4 is not valid."),
}),
('timerfd_create', c_int, [c_int, c_int],
"""int timerfd_create(int clockid, int flags);""",
-1, {
}),
('timerfd_settime', c_int, [c_int, c_int,
'ctypes.POINTER(glibc.itimerspec)',
'ctypes.POINTER(glibc.itimerspec)'],
"""int timerfd_settime(int fd, int flags,
const struct itimerspec *new_value,
struct itimerspec *old_value);""",
-1, {
}),
('timerfd_gettime', c_int, [c_int, 'ctypes.POINTER(glibc.itimerspec)'],
"""int timerfd_gettime(int fd, struct itimerspec *curr_value);""",
-1, {
}),
('pause', c_int, [],
"""int pause();""", -1, {
EINTR: (
"a signal was caught and the signal-catching function returned."
)
}),
('eventfd', c_int, [c_uint, c_int],
"""int eventfd(unsigned int initval, int flags);""", -1, {
EINVAL: (
"An unsupported value was specified in flags."),
EMFILE: (
"The per-process limit on open file descriptors has been"
" reached."),
ENFILE: (
"The system-wide limit on the total number of open files has"
" been reached."),
ENODEV: (
"Could not mount (internal) anonymous inode device."),
ENOMEM: (
"There was insufficient memory to create a new eventfd file"
" descriptor."),
}),
('eventfd_read', c_int, [c_uint, 'ctypes.POINTER(glibc.eventfd_t)'],
"""int eventfd_read(int fd, eventfd_t *value);""", -1, {}),
('eventfd_write', c_int, [c_uint, 'glibc.eventfd_t'],
"""int eventfd_write(int fd, eventfd_t value);""", -1, {}),
('clock_getres', c_int, ['glibc.clockid_t',
'ctypes.POINTER(glibc.timespec)'],
"""int clock_getres(clockid_t clk_id, struct timespec *res);""", -1, {
EFAULT: (
"res points outside the accessible address space."),
EINVAL: (
"The clk_id specified is not supported on this system."),
}),
('clock_gettime', c_int, ['glibc.clockid_t',
'ctypes.POINTER(glibc.timespec)'],
"""int clock_gettime(clockid_t clk_id, struct timespec *tp);""", -1, {
EFAULT: (
"tp points outside the accessible address space."),
EINVAL: (
"The clk_id specified is not supported on this system."),
}),
('clock_settime', c_int, ['glibc.clockid_t',
'ctypes.POINTER(glibc.timespec)'],
"""int clock_settime(clockid_t clk_id, const struct timespec *tp);""",
-1, {
EFAULT: (
"tp points outside the accessible address space."),
EINVAL: (
"The clk_id specified is not supported on this system."),
EPERM: (
"clock_settime() does not have permission to set the clock"
" indicated."),
}),
)
def _glibc_func(name, restype, argtypes, doc,
error_result=None, errno_map=None):
if name.startswith('pthread_'):
func = getattr(_pthread, name)
else:
func = getattr(_glibc, name)
_globals = {'ctypes': ctypes, 'glibc': _mod}
func.argtypes = [
eval(argtype, _globals) if isinstance(argtype, str) else argtype
for argtype in argtypes
]
func.restype = (
eval(restype, _globals) if isinstance(restype, str) else restype)
if errno_map is not None and error_result == 'pthread':
# Use a variant of error-code to errno translator that is specific
# to pthread_* family of functions that don't touch errno
def pthread_errcheck(result, func, arguments):
if result != 0:
raise OSError(result, errno_map.get(
result, os.strerror(result)))
return result
func.errcheck = pthread_errcheck
elif errno_map is not None:
# Use built-in error-code to errno translator
def std_errcheck(result, func, arguments):
if result == error_result:
errno = get_errno()
raise OSError(errno, errno_map.get(errno, os.strerror(errno)))
return result
func.errcheck = std_errcheck
return func
for info in _glibc_functions:
_mod.lazily(info[0], _glibc_func, info)
del info
del _glibc_functions
|