From d171ebdbd23c1c9f41f7c7aa54cf31bdb639b8c7 Mon Sep 17 00:00:00 2001 From: Helmut Grohne Date: Fri, 22 Mar 2024 18:45:05 +0100 Subject: add convenience functions for stat to AtLocationLike These are the is_* family and exists all from pathlib.Path. --- linuxnamespaces/atlocation.py | 94 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/linuxnamespaces/atlocation.py b/linuxnamespaces/atlocation.py index c534150..be9d17c 100644 --- a/linuxnamespaces/atlocation.py +++ b/linuxnamespaces/atlocation.py @@ -8,9 +8,11 @@ code for doing so. """ import enum +import errno import os import os.path import pathlib +import stat import typing @@ -29,6 +31,9 @@ class AtFlags(enum.IntFlag): AT_EMPTY_PATH = 0x1000 +_IGNORED_ERRNOS = frozenset((errno.ENOENT, errno.ENOTDIR, errno.ELOOP)) + + class AtLocation: """Represent a location in the filesystem suitable for use with the at-family of syscalls. If flags has the AT_EMPTY_PATH bit set, the @@ -217,6 +222,18 @@ class AtLocation: follow_symlinks=follow_symlinks, ) + def exists(self) -> bool: + """Report whether the location refers to an existing filesystem object. + Similar to pathlib.Path.exists. + """ + try: + self.stat() + except OSError as err: + if err.errno in _IGNORED_ERRNOS: + return False + raise + return True + def is_absolute(self) -> bool: """Report whether the location is absolute or not. Not that any location with an a valid filedescriptor is considered absolute as it is @@ -224,6 +241,83 @@ class AtLocation: """ return self.fd >= 0 or pathlib.Path(self.location).is_absolute() + def is_block_device(self) -> bool: + """Report whether the location refers to a block device. Similar to + pathlib.Path.is_block_device. + """ + try: + return stat.S_ISBLK(self.stat().st_mode) + except OSError as err: + if err.errno in _IGNORED_ERRNOS: + return False + raise + + def is_char_device(self) -> bool: + """Report whether the location refers to a character device. Similar to + pathlib.Path.is_char_device. + """ + try: + return stat.S_ISCHR(self.stat().st_mode) + except OSError as err: + if err.errno in _IGNORED_ERRNOS: + return False + raise + + def is_dir(self) -> bool: + """Report whether the location refers to a directory. Similar to + pathlib.Path.is_dir. + """ + try: + return stat.S_ISDIR(self.stat().st_mode) + except OSError as err: + if err.errno in _IGNORED_ERRNOS: + return False + raise + + def is_fifo(self) -> bool: + """Report whether the location refers to a FIFO. Similar to + pathlib.Path.is_fifo. + """ + try: + return stat.S_ISFIFO(self.stat().st_mode) + except OSError as err: + if err.errno in _IGNORED_ERRNOS: + return False + raise + + def is_file(self) -> bool: + """Report whether the location refers to a regular file. Similar to + pathlib.Path.is_file. + """ + try: + return stat.S_ISREG(self.stat().st_mode) + except OSError as err: + if err.errno in _IGNORED_ERRNOS: + return False + raise + + def is_socket(self) -> bool: + """Report whether the location refers to a socket. Similar to + pathlib.Path.is_socket. + """ + try: + return stat.S_ISSOCK(self.stat().st_mode) + except OSError as err: + if err.errno in _IGNORED_ERRNOS: + return False + raise + + def is_symlink(self) -> bool: + """Report whether the location refers to a symbolic link. Similar to + pathlib.Path.is_symlink. + """ + try: + return stat.S_ISLNK(self.stat().st_mode) + except OSError as err: + if err.errno in _IGNORED_ERRNOS: + return False + raise + def link(self, dst: "AtLocationLike") -> None: """Wrapper for os.link supplying src_dir_fd, dst_dir_fd and follow_symlinks. -- cgit v1.2.3