From 056c1f964f55adedc17f8d7bddef1f48c73852c7 Mon Sep 17 00:00:00 2001 From: Helmut Grohne Date: Fri, 17 May 2024 10:54:40 +0200 Subject: add a splice syscall wrapper --- linuxnamespaces/syscalls.py | 52 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/linuxnamespaces/syscalls.py b/linuxnamespaces/syscalls.py index 2a35a69..11800c6 100644 --- a/linuxnamespaces/syscalls.py +++ b/linuxnamespaces/syscalls.py @@ -352,6 +352,16 @@ class PrctlOption(enum.IntEnum): PR_CAP_AMBIENT = 47 +class SpliceFlags(enum.IntFlag): + """This value may be supplied to splice(2) as flags.""" + + NONE = 0 + MOVE = 1 + NONBLOCK = 2 + MORE = 4 + GIFT = 8 + + class UmountFlags(enum.IntFlag): """This value may be supplied to umount2(2) as flags.""" @@ -690,6 +700,48 @@ def setns(fd: int, nstype: CloneFlags = CloneFlags.NONE) -> None: call_libc("setns", fd, int(nstype)) +@dataclasses.dataclass +class SpliceResult: + """Return type for splice(2) capturing out arguments.""" + + copied: int + off_int: int | None + off_out: int | None + + +def splice( + fd_in: int, + off_in: int | None, + fd_out: int, + off_out: int | None, + length: int, + flags: SpliceFlags = SpliceFlags.NONE, +) -> SpliceResult: + """Python wrapper for splice(2). Unlike the syscall, the offset arguments + are not output arguments. Instead, they're returned as SpliceResult. + """ + if fd_in < 0 or fd_out < 0: + raise ValueError("invalid file descriptor") + if off_in is None: + p_off_in = None + else: + c_off_in = ctypes.c_int64(off_in) + p_off_in = ctypes.byref(c_off_in) + if off_out is None: + p_off_out = None + else: + c_off_out = ctypes.c_int64(off_out) + p_off_out = ctypes.byref(c_off_out) + ret = call_libc( + "splice", fd_in, p_off_in, fd_out, p_off_out, length, int(flags) + ) + return SpliceResult( + ret, + None if off_in is None else c_off_in.value, + None if off_out is None else c_off_out.value, + ) + + def umount( path: PathConvertible, flags: UmountFlags = UmountFlags.NONE ) -> None: -- cgit v1.2.3