예제 #1
0
def test_recover_fd_path_no_execute(tmp_path: pathlib.Path) -> None:
    os.mkdir(tmp_path / "a")
    os.mkdir(tmp_path / "a/b")

    old_func = getattr(nixutil.plat_util, "try_recover_fd_path", None)
    if old_func is not None:
        del nixutil.plat_util.try_recover_fd_path

    try:
        with managed_open(tmp_path / "a/b", os.O_RDONLY) as b_dfd:
            try:
                # 0o400 is "r--------"; i.e. read permission but not execute permission.
                # That allows us to list the directory, but not access files in it.
                os.chmod(tmp_path / "a", 0o400)

                # Fails with ENOENT after failing to stat() any of the entries and reaching the end
                with pytest.raises(FileNotFoundError):
                    nixutil.recover_fd_path(b_dfd)

            finally:
                # chmod() it back so pytest can remove it
                os.chmod(tmp_path / "a", 0o755)

    finally:
        if old_func is not None:
            nixutil.plat_util.try_recover_fd_path = old_func
예제 #2
0
def test_recover_fd_path_bad_file() -> None:
    # Negative file descriptors always raise an error
    for i in range(-10, 0):
        with pytest.raises(OSError, match=r"[bB]ad file descriptor"):
            nixutil.recover_fd_path(i)

    # This is larger than any file descriptor that we should be allowed to open
    with pytest.raises(OSError, match=r"[bB]ad file descriptor"):
        nixutil.recover_fd_path(os.sysconf("SC_OPEN_MAX"))

    # Sockets and pipes aren't allowed

    with socket.socket() as sock:
        with pytest.raises(OSError, match=r"[nN]ot supported"):
            nixutil.recover_fd_path(sock.fileno())

    r_fd, w_fd = os.pipe()
    try:
        with pytest.raises(OSError, match=r"[nN]ot supported"):
            nixutil.recover_fd_path(r_fd)
        with pytest.raises(OSError, match=r"[nN]ot supported"):
            nixutil.recover_fd_path(w_fd)
    finally:
        os.close(r_fd)
        os.close(w_fd)
예제 #3
0
def test_recover_fd_path_execute(tmp_path: pathlib.Path) -> None:
    os.mkdir(tmp_path / "a")
    os.mkdir(tmp_path / "a/b")

    old_func = getattr(nixutil.plat_util, "try_recover_fd_path", None)
    if old_func is not None:
        del nixutil.plat_util.try_recover_fd_path

    try:
        with managed_open(tmp_path / "a/b", os.O_RDONLY) as b_dfd:
            try:
                # 0o100 is "--x------"; i.e. execute permission but not read permission.
                # That allows us to access files in the directory, but not list it.
                os.chmod(tmp_path / "a", 0o100)

                # Fails with EACCES when trying to open the directory
                with pytest.raises(PermissionError):
                    nixutil.recover_fd_path(b_dfd)

            finally:
                # chmod() it back so pytest can remove it
                os.chmod(tmp_path / "a", 0o755)

    finally:
        if old_func is not None:
            nixutil.plat_util.try_recover_fd_path = old_func
예제 #4
0
def test_recover_fd_path_dir(tmp_path: pathlib.Path) -> None:
    with managed_open(tmp_path, os.O_RDONLY) as fd:
        assert nixutil.recover_fd_path(fd) == os.path.realpath(tmp_path)

    with managed_open(tmp_path, os.O_RDONLY) as fd:
        assert nixutil.recover_fd_path(fd) == os.path.realpath(tmp_path)

    with managed_open("/", os.O_RDONLY) as fd:
        assert nixutil.recover_fd_path(fd) == "/"
예제 #5
0
def test_recover_fd_path_dir_fallback(tmp_path: pathlib.Path) -> None:
    old_func = getattr(nixutil.plat_util, "try_recover_fd_path", None)
    if old_func is not None:
        del nixutil.plat_util.try_recover_fd_path

    try:
        with managed_open(tmp_path, os.O_RDONLY) as fd:
            assert nixutil.recover_fd_path(fd) == os.path.realpath(tmp_path)

        # Without OS-specific help, ENOTSUP is raised for regular files
        with open(tmp_path / "a", "w") as file:
            with pytest.raises(OSError, match=r"[nN]ot supported"):
                nixutil.recover_fd_path(file.fileno())

    finally:
        if old_func is not None:
            nixutil.plat_util.try_recover_fd_path = old_func
예제 #6
0
def test_recover_fd_path_link(tmp_path: pathlib.Path) -> None:
    os.mkdir(tmp_path / "dir")
    os.symlink("dir", tmp_path / "link")

    with managed_open(tmp_path / "link", os.O_RDONLY) as fd:
        # The path that's returned is the path *after* resolving symlinks
        assert nixutil.recover_fd_path(fd) == os.path.realpath(tmp_path /
                                                               "dir")
예제 #7
0
def test_recover_fd_path_moved(tmp_path: pathlib.Path) -> None:
    os.mkdir(tmp_path / "dir")

    with managed_open(tmp_path / "dir", os.O_RDONLY) as fd:
        os.rename(tmp_path / "dir", tmp_path / "dir2")

        # The path that's returned is the *new* path
        assert nixutil.recover_fd_path(fd) == os.path.realpath(tmp_path /
                                                               "dir2")
예제 #8
0
def test_recover_fd_path_file(tmp_path: pathlib.Path) -> None:
    with open(tmp_path / "a", "w") as file:
        try:
            assert nixutil.recover_fd_path(file.fileno()) == os.path.realpath(
                tmp_path / "a")
        except OSError as ex:
            if ex.errno == errno.ENOTSUP:
                pytest.skip("Recovering paths of regular files not supported")
            else:
                raise
예제 #9
0
def test_recover_fd_path_dir_deleted(tmp_path: pathlib.Path) -> None:
    os.mkdir(tmp_path / "a")

    with managed_open(tmp_path / "a", os.O_RDONLY) as fd:
        os.rmdir(tmp_path / "a")

        # Either it returns the correct path or raises a FileNotFoundError.
        try:
            assert nixutil.recover_fd_path(fd) == os.path.join(
                os.path.realpath(tmp_path), "a")
        except FileNotFoundError:
            pass