summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2013-03-04 19:18:06 +0000
committerLars Wirzenius <liw@liw.fi>2013-03-04 19:18:06 +0000
commitcca1cb28721336085cdee447b4d8ceda2e7c3ca3 (patch)
treec39d49bdbc310b6a52207b1eb8a98b5a7a42554a
parentd1521cfa06653251896130388a7c896f7cf02079 (diff)
parent446a065e1de42ae45ddc28784f9325f89bcf6820 (diff)
downloadobnam-cca1cb28721336085cdee447b4d8ceda2e7c3ca3.tar.gz
Handle signed/unsigned stat values correctly
-rw-r--r--_obnammodule.c25
-rw-r--r--obnamlib/metadata.py57
-rw-r--r--obnamlib/metadata_tests.py39
-rw-r--r--obnamlib/plugins/backup_plugin.py3
4 files changed, 86 insertions, 38 deletions
diff --git a/_obnammodule.c b/_obnammodule.c
index 55d8eef0..f160d5af 100644
--- a/_obnammodule.c
+++ b/_obnammodule.c
@@ -31,6 +31,8 @@
*/
+#define _FILE_OFFSET_BITS 64
+
#include <Python.h>
@@ -110,24 +112,25 @@ lstat_wrapper(PyObject *self, PyObject *args)
ret = lstat(filename, &st);
if (ret == -1)
ret = errno;
- return Py_BuildValue("iLLLLLLLLLLLLLLLL",
+
+ return Py_BuildValue("iKKKKKKKLLLLKLKLK",
ret,
- (long long) st.st_dev,
- (long long) st.st_ino,
- (long long) st.st_mode,
- (long long) st.st_nlink,
- (long long) st.st_uid,
- (long long) st.st_gid,
- (long long) st.st_rdev,
+ (unsigned long long) st.st_dev,
+ (unsigned long long) st.st_ino,
+ (unsigned long long) st.st_mode,
+ (unsigned long long) st.st_nlink,
+ (unsigned long long) st.st_uid,
+ (unsigned long long) st.st_gid,
+ (unsigned long long) st.st_rdev,
(long long) st.st_size,
(long long) st.st_blksize,
(long long) st.st_blocks,
(long long) st.st_atim.tv_sec,
- (long long) st.st_atim.tv_nsec,
+ (unsigned long long) st.st_atim.tv_nsec,
(long long) st.st_mtim.tv_sec,
- (long long) st.st_mtim.tv_nsec,
+ (unsigned long long) st.st_mtim.tv_nsec,
(long long) st.st_ctim.tv_sec,
- (long long) st.st_ctim.tv_nsec);
+ (unsigned long long) st.st_ctim.tv_nsec);
}
diff --git a/obnamlib/metadata.py b/obnamlib/metadata.py
index a3c1bea0..bba229fe 100644
--- a/obnamlib/metadata.py
+++ b/obnamlib/metadata.py
@@ -286,24 +286,45 @@ def encode_metadata(metadata):
if getattr(metadata, name) is not None:
flags |= (1 << i)
- packed = metadata_format.pack(flags,
- metadata.st_mode or 0,
- metadata.st_mtime_sec or 0,
- metadata.st_mtime_nsec or 0,
- metadata.st_atime_sec or 0,
- metadata.st_atime_nsec or 0,
- metadata.st_nlink or 0,
- metadata.st_size or 0,
- metadata.st_uid or 0,
- metadata.st_gid or 0,
- metadata.st_dev or 0,
- metadata.st_ino or 0,
- metadata.st_blocks or 0,
- len(metadata.groupname or ''),
- len(metadata.username or ''),
- len(metadata.target or ''),
- len(metadata.md5 or ''),
- len(metadata.xattr or ''))
+ try:
+ packed = metadata_format.pack(flags,
+ metadata.st_mode or 0,
+ metadata.st_mtime_sec or 0,
+ metadata.st_mtime_nsec or 0,
+ metadata.st_atime_sec or 0,
+ metadata.st_atime_nsec or 0,
+ metadata.st_nlink or 0,
+ metadata.st_size or 0,
+ metadata.st_uid or 0,
+ metadata.st_gid or 0,
+ metadata.st_dev or 0,
+ metadata.st_ino or 0,
+ metadata.st_blocks or 0,
+ len(metadata.groupname or ''),
+ len(metadata.username or ''),
+ len(metadata.target or ''),
+ len(metadata.md5 or ''),
+ len(metadata.xattr or ''))
+ except TypeError, e: # pragma: no cover
+ logging.error('ERROR: Packing error due to %s' % str(e))
+ logging.error('ERROR: st_mode=%s' % repr(metadata.st_mode))
+ logging.error('ERROR: st_mtime_sec=%s' % repr(metadata.st_mtime_sec))
+ logging.error('ERROR: st_mtime_nsec=%s' % repr(metadata.st_mtime_nsec))
+ logging.error('ERROR: st_atime_sec=%s' % repr(metadata.st_atime_sec))
+ logging.error('ERROR: st_atime_nsec=%s' % repr(metadata.st_atime_nsec))
+ logging.error('ERROR: st_nlink=%s' % repr(metadata.st_nlink))
+ logging.error('ERROR: st_size=%s' % repr(metadata.st_size))
+ logging.error('ERROR: st_uid=%s' % repr(metadata.st_uid))
+ logging.error('ERROR: st_gid=%s' % repr(metadata.st_gid))
+ logging.error('ERROR: st_dev=%s' % repr(metadata.st_dev))
+ logging.error('ERROR: st_ino=%s' % repr(metadata.st_ino))
+ logging.error('ERROR: st_blocks=%s' % repr(metadata.st_blocks))
+ logging.error('ERROR: groupname=%s' % repr(metadata.groupname))
+ logging.error('ERROR: username=%s' % repr(metadata.username))
+ logging.error('ERROR: target=%s' % repr(metadata.target))
+ logging.error('ERROR: md5=%s' % repr(metadata.md5))
+ logging.error('ERROR: xattr=%s' % repr(metadata.xattr))
+ raise
return (packed +
(metadata.groupname or '') +
(metadata.username or '') +
diff --git a/obnamlib/metadata_tests.py b/obnamlib/metadata_tests.py
index 062b6d83..286a86b9 100644
--- a/obnamlib/metadata_tests.py
+++ b/obnamlib/metadata_tests.py
@@ -239,6 +239,17 @@ class SetMetadataTests(unittest.TestCase):
class MetadataCodingTests(unittest.TestCase):
+ def equal(self, meta1, meta2):
+ for name in dir(meta1):
+ if name in obnamlib.metadata.metadata_fields:
+ value1 = getattr(meta1, name)
+ value2 = getattr(meta2, name)
+ self.assertEqual(
+ value1,
+ value2,
+ 'attribute %s must be equal (%s vs %s)' %
+ (name, value1, value2))
+
def test_round_trip(self):
metadata = obnamlib.metadata.Metadata(st_mode=1,
st_mtime_sec=2,
@@ -258,13 +269,7 @@ class MetadataCodingTests(unittest.TestCase):
md5='checksum')
encoded = obnamlib.encode_metadata(metadata)
decoded = obnamlib.decode_metadata(encoded)
- for name in dir(metadata):
- if name in obnamlib.metadata.metadata_fields:
- self.assertEqual(getattr(metadata, name),
- getattr(decoded, name),
- 'attribute %s must be equal (%s vs %s)' %
- (name, getattr(metadata, name),
- getattr(decoded, name)))
+ self.equal(metadata, decoded)
def test_round_trip_for_None_values(self):
metadata = obnamlib.metadata.Metadata()
@@ -275,3 +280,23 @@ class MetadataCodingTests(unittest.TestCase):
self.assertEqual(getattr(decoded, name), None,
'attribute %s must be None' % name)
+ def test_round_trip_for_maximum_values(self):
+ unsigned_max = 2**64 - 1
+ signed_max = 2**63 - 1
+ metadata = obnamlib.metadata.Metadata(
+ st_mode=unsigned_max,
+ st_mtime_sec=signed_max,
+ st_mtime_nsec=unsigned_max,
+ st_nlink=unsigned_max,
+ st_size=signed_max,
+ st_uid=unsigned_max,
+ st_blocks=signed_max,
+ st_dev=unsigned_max,
+ st_gid=unsigned_max,
+ st_ino=unsigned_max,
+ st_atime_sec=signed_max,
+ st_atime_nsec=unsigned_max)
+ encoded = obnamlib.encode_metadata(metadata)
+ decoded = obnamlib.decode_metadata(encoded)
+ self.equal(metadata, decoded)
+
diff --git a/obnamlib/plugins/backup_plugin.py b/obnamlib/plugins/backup_plugin.py
index 9279d748..e04fea19 100644
--- a/obnamlib/plugins/backup_plugin.py
+++ b/obnamlib/plugins/backup_plugin.py
@@ -327,10 +327,9 @@ class BackupPlugin(obnamlib.ObnamPlugin):
'Attempting to unlock shared trees because of error')
self.repo.unlock_shared()
except BaseException, e2:
- logging.error(
+ logging.warning(
'Error while unlocking due to error: %s' % str(e2))
logging.debug(traceback.format_exc())
- raise
else:
logging.info('Successfully unlocked')