I want to make syscall
in Python and the function is not in libc
, is there a way to do it in Python?
More specifically, I want to call getdents
, whose manpage says
Note: There are no glibc wrappers for these system calls;
All existing related solutions I found on the web uses ctypes
with libc.so
: for example.
Please don't question why I want to use getdents
directly, I have a very specific reason to do that, and it would be distracting to discuss in this question. Thank you.
syscall() is a small library function that invokes the system call whose assembly language interface has the specified number with the specified arguments. Employing syscall() is useful, for example, when invoking a system call that has no wrapper function in the C library.
Processing arguments import sys # argv is a list of strings containing the commandline params # argv[0] is always the name of the invoked command for arg in sys.argv: print arg argc = len(sys.argv) fork import os # fork creates a child process.
In Linux, you can call almost all system calls if you can find their kernel export (do cat /proc/kallsysms | grep sys_ for an example). There is a minor "trick" to get around a protection in most syscalls (those which accept a user mode *), by setting the data segment (KERNEL_DS).
Libc exposes a function to invoke "custom" syscalls: long syscall(long number, ...);
syscall()
is a small library function that invokes the system call whose assembly language interface has the specifiednumber
with the specified arguments. Employingsyscall()
is useful, for example, when invoking a system call that has no wrapper function in the C library.
Just access this function like any foreign function:
import ctypes libc = ctypes.CDLL(None) syscall = libc.syscall
e.g.
syscall(39) # 39 = getpid, but you get the gist
Or to translate the example in the man page:
import os, ctypes off_t = ctypes.c_long # YMMV __NR_getdents = 78 # YMMV class linux_dirent(ctypes.Structure): _fields_ = [ ('d_ino', ctypes.c_long), ('d_off', off_t), ('d_reclen', ctypes.c_ushort), ('d_name', ctypes.c_char) ] _getdents = ctypes.CDLL(None).syscall _getdents.restype = ctypes.c_int _getdents.argtypes = ctypes.c_long, ctypes.c_uint, ctypes.POINTER(ctypes.c_char), ctypes.c_uint fd = os.open('/tmp/', os.O_RDONLY | os.O_DIRECTORY) buf = ctypes.ARRAY(ctypes.c_char, 1024)() while True: nread = _getdents(__NR_getdents, fd, buf, len(buf)) if nread == -1: raise OSError('getdents') elif nread == 0: break pos = 0 while pos < nread: d = linux_dirent.from_buffer(buf, pos) name = buf[pos + linux_dirent.d_name.offset : pos + d.d_reclen] name = name[:name.index('\0')] print 'name:', name pos += d.d_reclen
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With