Blame osbuild/util/linux.py

Packit a20ca0
"""Linux API Access
Packit a20ca0
Packit a20ca0
This module provides access to linux system-calls and other APIs, in particular
Packit a20ca0
those not provided by the python standard library. The idea is to provide
Packit a20ca0
universal wrappers with broad access to linux APIs. Convenience helpers and
Packit a20ca0
higher-level abstractions are beyond the scope of this module.
Packit a20ca0
Packit a20ca0
In some cases it is overly complex to provide universal access to a specifc
Packit a20ca0
API. Hence, the API might be restricted to a reduced subset of its
Packit a20ca0
functionality, just to make sure we can actually implement the wrappers in a
Packit a20ca0
reasonable manner.
Packit a20ca0
"""
Packit a20ca0
Packit a20ca0
Packit a20ca0
import array
Packit a20ca0
import fcntl
Packit a20ca0
Packit a20ca0
Packit a20ca0
__all__ = [
Packit a20ca0
    "ioctl_get_immutable",
Packit a20ca0
    "ioctl_toggle_immutable",
Packit a20ca0
]
Packit a20ca0
Packit a20ca0
Packit a20ca0
# NOTE: These are wrong on at least ALPHA and SPARC. They use different
Packit a20ca0
#       ioctl number setups. We should fix this, but this is really awkward
Packit a20ca0
#       in standard python.
Packit a20ca0
#       Our tests will catch this, so we will not accidentally run into this
Packit a20ca0
#       on those architectures.
Packit a20ca0
FS_IOC_GETFLAGS = 0x80086601
Packit a20ca0
FS_IOC_SETFLAGS = 0x40086602
Packit a20ca0
Packit a20ca0
FS_IMMUTABLE_FL = 0x00000010
Packit a20ca0
Packit a20ca0
Packit a20ca0
def ioctl_get_immutable(fd: int):
Packit a20ca0
    """Query FS_IMMUTABLE_FL
Packit a20ca0
Packit a20ca0
    This queries the `FS_IMMUTABLE_FL` flag on a specified file.
Packit a20ca0
Packit a20ca0
    Arguments
Packit a20ca0
    ---------
Packit a20ca0
    fd
Packit a20ca0
        File-descriptor to operate on.
Packit a20ca0
Packit a20ca0
    Returns
Packit a20ca0
    -------
Packit a20ca0
    bool
Packit a20ca0
        Whether the `FS_IMMUTABLE_FL` flag is set or not.
Packit a20ca0
Packit a20ca0
    Raises
Packit a20ca0
    ------
Packit a20ca0
    OSError
Packit a20ca0
        If the underlying ioctl fails, a matching `OSError` will be raised.
Packit a20ca0
    """
Packit a20ca0
Packit a20ca0
    if not isinstance(fd, int) or fd < 0:
Packit a20ca0
        raise ValueError()
Packit a20ca0
Packit a20ca0
    flags = array.array('L', [0])
Packit a20ca0
    fcntl.ioctl(fd, FS_IOC_GETFLAGS, flags, True)
Packit a20ca0
    return bool(flags[0] & FS_IMMUTABLE_FL)
Packit a20ca0
Packit a20ca0
Packit a20ca0
def ioctl_toggle_immutable(fd: int, set_to: bool):
Packit a20ca0
    """Toggle FS_IMMUTABLE_FL
Packit a20ca0
Packit a20ca0
    This toggles the `FS_IMMUTABLE_FL` flag on a specified file. It can both set
Packit a20ca0
    and clear the flag.
Packit a20ca0
Packit a20ca0
    Arguments
Packit a20ca0
    ---------
Packit a20ca0
    fd
Packit a20ca0
        File-descriptor to operate on.
Packit a20ca0
    set_to
Packit a20ca0
        Whether to set the `FS_IMMUTABLE_FL` flag or not.
Packit a20ca0
Packit a20ca0
    Raises
Packit a20ca0
    ------
Packit a20ca0
    OSError
Packit a20ca0
        If the underlying ioctl fails, a matching `OSError` will be raised.
Packit a20ca0
    """
Packit a20ca0
Packit a20ca0
    if not isinstance(fd, int) or fd < 0:
Packit a20ca0
        raise ValueError()
Packit a20ca0
Packit a20ca0
    flags = array.array('L', [0])
Packit a20ca0
    fcntl.ioctl(fd, FS_IOC_GETFLAGS, flags, True)
Packit a20ca0
    if set_to:
Packit a20ca0
        flags[0] |= FS_IMMUTABLE_FL
Packit a20ca0
    else:
Packit a20ca0
        flags[0] &= ~FS_IMMUTABLE_FL
Packit a20ca0
    fcntl.ioctl(fd, FS_IOC_SETFLAGS, flags, False)