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