diff options
-rw-r--r-- | gemato/verify.py | 6 | ||||
-rw-r--r-- | tests/test_verify.py | 10 |
2 files changed, 16 insertions, 0 deletions
diff --git a/gemato/verify.py b/gemato/verify.py index 8e6cbd1..05e568d 100644 --- a/gemato/verify.py +++ b/gemato/verify.py @@ -43,6 +43,7 @@ def get_file_metadata(path, hashes): StopIteration, or close it explicitly. """ + open_exc = None try: # we want O_NONBLOCK to avoid blocking when opening pipes fd = os.open(path, os.O_RDONLY | os.O_NONBLOCK) @@ -55,6 +56,7 @@ def get_file_metadata(path, hashes): # EOPNOTSUPP = opening UNIX socket on FreeBSD exists = True opened = False + open_exc = err else: raise else: @@ -74,6 +76,10 @@ def get_file_metadata(path, hashes): else: st = os.stat(path) + # safety check: if open() failed, it should not be a regular file + if not opened and stat.S_ISREG(st.st_mode): + raise open_exc + # 2. st_dev yield st.st_dev diff --git a/tests/test_verify.py b/tests/test_verify.py index 8890e1a..0c3fba9 100644 --- a/tests/test_verify.py +++ b/tests/test_verify.py @@ -4,11 +4,13 @@ # Licensed under the terms of 2-clause BSD license import contextlib +import errno import itertools import os import os.path import socket import stat +import unittest.mock import pytest @@ -560,3 +562,11 @@ def test_entry_compatibility(a_cls, a_name, a_args, b_cls, b_name, e1 = new_manifest_entry(a_cls, a_name, *a_args) e2 = new_manifest_entry(b_cls, b_name, *b_args) assert verify_entry_compatibility(e1, e2) == (expected, diff) + + +def test_get_file_metadata_fail_to_open_reg(test_tree): + """Regression test for when open() fails on a seemingly regular file""" + with unittest.mock.patch("os.open") as mock_open: + mock_open.side_effect = OSError(errno.ENXIO, "mocked error") + with pytest.raises(OSError): + list(get_file_metadata(test_tree / "regular-file", {})) |