summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gemato/exceptions.py12
-rw-r--r--gemato/verify.py15
-rw-r--r--tests/test_verify.py24
3 files changed, 48 insertions, 3 deletions
diff --git a/gemato/exceptions.py b/gemato/exceptions.py
index e580309..c9cb646 100644
--- a/gemato/exceptions.py
+++ b/gemato/exceptions.py
@@ -38,3 +38,15 @@ class ManifestMismatch(Exception):
self.path = path
self.entry = entry
self.diff = diff
+
+
+class ManifestCrossDevice(Exception):
+ """
+ An exception caused by attempting to cross filesystem boundaries.
+ """
+
+ def __init__(self, path):
+ self.path = path
+ super(ManifestCrossDevice, self).__init__(
+ "Path {} crosses filesystem boundaries, it must be IGNORE-d explicitly"
+ .format(path))
diff --git a/gemato/verify.py b/gemato/verify.py
index ef8092b..74791ee 100644
--- a/gemato/verify.py
+++ b/gemato/verify.py
@@ -13,7 +13,7 @@ import gemato.hash
import gemato.manifest
-def verify_path(path, e):
+def verify_path(path, e, expected_dev=None):
"""
Verify the file at system path @path against the data in entry @e.
The path/filename is not matched against the entry -- the correct
@@ -24,6 +24,11 @@ def verify_path(path, e):
the file at path and the Manifest entry. Each list element is
a tuple of (name, expected, got).
+ If @expected_dev is not None, verifies that the file resides
+ on specified device. If the device does not match, raises
+ ManifestCrossDevice exception. It can be used to verify that
+ the files do not cross filesystem boundaries.
+
Each name can be:
- __exists__ (boolean) to indicate whether the file existed,
- __type__ (string) as a human-readable description of file type,
@@ -70,6 +75,10 @@ def verify_path(path, e):
st = os.fstat(fd)
else:
st = os.stat(path)
+ if expected_dev is not None and st.st_dev != expected_dev:
+ if opened:
+ os.close(fd)
+ raise gemato.exceptions.ManifestCrossDevice(path)
if not opened or not stat.S_ISREG(st.st_mode):
if opened:
os.close(fd)
@@ -169,12 +178,12 @@ def verify_entry_compatibility(e1, e2):
return (ret, diff)
-def assert_path_verifies(path, e):
+def assert_path_verifies(path, e, expected_dev=None):
"""
Verify the path @path against entry @e. Raises an exception if it
does not pass the verification.
"""
- ret, diff = verify_path(path, e)
+ ret, diff = verify_path(path, e, expected_dev=expected_dev)
if not ret:
raise gemato.exceptions.ManifestMismatch(path, e, diff)
diff --git a/tests/test_verify.py b/tests/test_verify.py
index 4902ec8..bc41532 100644
--- a/tests/test_verify.py
+++ b/tests/test_verify.py
@@ -241,6 +241,30 @@ class EmptyFileVerificationTest(unittest.TestCase):
self.assertEqual(gemato.verify.verify_path(self.path, None),
(False, [('__exists__', False, True)]))
+ def testCrossFilesystem(self):
+ try:
+ st = os.stat('/proc')
+ except OSError:
+ raise unittest.SkipTest('Unable to stat /proc')
+
+ e = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', os.path.basename(self.path), '0'))
+ self.assertRaises(gemato.exceptions.ManifestCrossDevice,
+ gemato.verify.verify_path, self.path, e,
+ expected_dev=st.st_dev)
+
+ def testCrossFilesystemAssert(self):
+ try:
+ st = os.stat('/proc')
+ except OSError:
+ raise unittest.SkipTest('Unable to stat /proc')
+
+ e = gemato.manifest.ManifestEntryDATA.from_list(
+ ('DATA', os.path.basename(self.path), '0'))
+ self.assertRaises(gemato.exceptions.ManifestCrossDevice,
+ gemato.verify.assert_path_verifies, self.path, e,
+ expected_dev=st.st_dev)
+
class NonEmptyFileVerificationTest(unittest.TestCase):
def setUp(self):