diff options
author | Michał Górny <mgorny@gentoo.org> | 2022-09-17 18:30:57 +0200 |
---|---|---|
committer | Michał Górny <mgorny@gentoo.org> | 2022-09-17 18:30:57 +0200 |
commit | 3c251c8d655011ec2ee4ec02933e8e02163b4620 (patch) | |
tree | 225bc6dd8208e5c3ead9b6594dead4ac8d5dbafc | |
parent | 1cdca1a14706c46f9161c8eca319dad7b15e7cd6 (diff) | |
download | gemato-3c251c8d655011ec2ee4ec02933e8e02163b4620.tar.gz |
Fix a corner case when open() fails w/ NXIO/OPNOTSUPP on reg file
Closes: https://github.com/projg2/gemato/issues/21
Signed-off-by: Michał Górny <mgorny@gentoo.org>
-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", {})) |