diff options
author | Lars Wirzenius <liw@liw.fi> | 2012-11-17 18:06:59 +0000 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2012-11-17 18:06:59 +0000 |
commit | c730d554a92cdf9e313006cff3fd227023fb848f (patch) | |
tree | 267681ea9cd58dc622e03e7d9a71b4f31183f8e7 | |
parent | 4636212b3a1d8db5f7f8545a396145ffc59d9785 (diff) | |
parent | 5b0c891192ddeb8da579f83dfea8c5168597c8ba (diff) | |
download | obnam-c730d554a92cdf9e313006cff3fd227023fb848f.tar.gz |
Fix handling of value-less extended attributes
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | obnamlib/metadata.py | 30 | ||||
-rw-r--r-- | obnamlib/vfs_local.py | 2 |
3 files changed, 32 insertions, 2 deletions
@@ -20,6 +20,8 @@ Bug fixes: * Empty values for extended attributes are now backed up correctly. Previously they would cause an infinite loop. +* Extended attributes without values are now ignored. This is different + from attributes with empty values. Reported by Vladimir Elisseev. * An empty port number in sftp URLs is now handled correctly. Found based on report by Anton Shevtsov. * A bad performance bug when backing up full systems (starting from the diff --git a/obnamlib/metadata.py b/obnamlib/metadata.py index be3a46c9..eaca40fb 100644 --- a/obnamlib/metadata.py +++ b/obnamlib/metadata.py @@ -14,11 +14,14 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. +import errno import grp +import logging import os import pwd import stat import struct +import tracing import obnamlib @@ -127,10 +130,35 @@ def _cached_getgrgid(gid): # pragma: no cover def get_xattrs_as_blob(fs, filename): # pragma: no cover + tracing.trace('filename=%s' % filename) names = fs.llistxattr(filename) + tracing.trace('names=%s' % repr(names)) if not names: return None - values = [fs.lgetxattr(filename, name) for name in names] + + values = [] + for name in names[:]: + tracing.trace('trying name %s' % repr(name)) + try: + value = fs.lgetxattr(filename, name) + except OSError, e: + # On btrfs, at least, this can happen: the filesystem returns + # a list of attribute names, but then fails when looking up + # the value for one or more of the names. We pretend that the + # name was never returned in that case. + # + # Obviously this can happen due to race conditions as well. + if e.errno == errno.ENODATA: + names.remove(name) + logging.warning( + '%s has extended attribute named %s without value, ' + 'ignoring attribute' % (filename, name)) + else: + raise + else: + tracing.trace('lgetxattr(%s)=%s' % (name, value)) + values.append(value) + assert len(names) == len(values) name_blob = ''.join('%s\0' % name for name in names) diff --git a/obnamlib/vfs_local.py b/obnamlib/vfs_local.py index e4b6b274..9b456f9f 100644 --- a/obnamlib/vfs_local.py +++ b/obnamlib/vfs_local.py @@ -168,7 +168,7 @@ class LocalFS(obnamlib.VirtualFileSystem): def lgetxattr(self, filename, attrname): # pragma: no cover ret = obnamlib._obnam.lgetxattr(self.join(filename), attrname) if type(ret) is int: - raise OSError((ret, os.strerror(ret), filename)) + raise OSError(ret, os.strerror(ret), filename) return ret def lsetxattr(self, filename, attrname, attrvalue): # pragma: no cover |