summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linuxnamespaces/syscalls.py52
1 files changed, 52 insertions, 0 deletions
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: