|  | @@ -5,6 +5,7 @@ import os
 | 
	
		
			
				|  |  |  import socket
 | 
	
		
			
				|  |  |  import stat
 | 
	
		
			
				|  |  |  import sys
 | 
	
		
			
				|  |  | +from xattr import xattr, XATTR_NOFOLLOW
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  from . import NS_ARCHIVE_METADATA, NS_ARCHIVE_ITEMS, NS_ARCHIVE_CHUNKS, NS_CHUNK
 | 
	
		
			
				|  |  |  from .chunkifier import chunkify
 | 
	
	
		
			
				|  | @@ -144,6 +145,13 @@ class Archive(object):
 | 
	
		
			
				|  |  |              raise Exception('Unknown archive item type %r' % item['mode'])
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def restore_attrs(self, path, item, symlink=False):
 | 
	
		
			
				|  |  | +        if item['xattrs']:
 | 
	
		
			
				|  |  | +            try:
 | 
	
		
			
				|  |  | +                xa = xattr(path, XATTR_NOFOLLOW)
 | 
	
		
			
				|  |  | +                for k, v in item['xattrs'].items():
 | 
	
		
			
				|  |  | +                    xa.set(k, v)
 | 
	
		
			
				|  |  | +            except IOError:
 | 
	
		
			
				|  |  | +                pass
 | 
	
		
			
				|  |  |          if have_lchmod:
 | 
	
		
			
				|  |  |              os.lchmod(path, item['mode'])
 | 
	
		
			
				|  |  |          elif not symlink:
 | 
	
	
		
			
				|  | @@ -179,28 +187,33 @@ class Archive(object):
 | 
	
		
			
				|  |  |          self.store.commit()
 | 
	
		
			
				|  |  |          cache.save()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    def stat_attrs(self, st):
 | 
	
		
			
				|  |  | +    def stat_attrs(self, st, path):
 | 
	
		
			
				|  |  | +        try:
 | 
	
		
			
				|  |  | +            xattrs = dict(xattr(path, XATTR_NOFOLLOW))
 | 
	
		
			
				|  |  | +        except IOError:
 | 
	
		
			
				|  |  | +            xattrs = None
 | 
	
		
			
				|  |  |          return {
 | 
	
		
			
				|  |  |              'mode': st.st_mode,
 | 
	
		
			
				|  |  |              'uid': st.st_uid, 'user': uid2user(st.st_uid),
 | 
	
		
			
				|  |  |              'gid': st.st_gid, 'group': gid2group(st.st_gid),
 | 
	
		
			
				|  |  |              'atime': st.st_atime, 'mtime': st.st_mtime,
 | 
	
		
			
				|  |  | +            'xattrs': xattrs,
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def process_dir(self, path, st):
 | 
	
		
			
				|  |  |          item = {'path': path.lstrip('/\\:')}
 | 
	
		
			
				|  |  | -        item.update(self.stat_attrs(st))
 | 
	
		
			
				|  |  | +        item.update(self.stat_attrs(st, path))
 | 
	
		
			
				|  |  |          self.items.append(item)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def process_fifo(self, path, st):
 | 
	
		
			
				|  |  |          item = {'path': path.lstrip('/\\:')}
 | 
	
		
			
				|  |  | -        item.update(self.stat_attrs(st))
 | 
	
		
			
				|  |  | +        item.update(self.stat_attrs(st, path))
 | 
	
		
			
				|  |  |          self.items.append(item)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def process_symlink(self, path, st):
 | 
	
		
			
				|  |  |          source = os.readlink(path)
 | 
	
		
			
				|  |  |          item = {'path': path.lstrip('/\\:'), 'source': source}
 | 
	
		
			
				|  |  | -        item.update(self.stat_attrs(st))
 | 
	
		
			
				|  |  | +        item.update(self.stat_attrs(st, path))
 | 
	
		
			
				|  |  |          self.items.append(item)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def process_file(self, path, st, cache):
 | 
	
	
		
			
				|  | @@ -240,7 +253,7 @@ class Archive(object):
 | 
	
		
			
				|  |  |                      size += len(chunk)
 | 
	
		
			
				|  |  |              cache.memorize_file_chunks(path_hash, st, ids)
 | 
	
		
			
				|  |  |          item = {'path': safe_path, 'chunks': chunks, 'size': size}
 | 
	
		
			
				|  |  | -        item.update(self.stat_attrs(st))
 | 
	
		
			
				|  |  | +        item.update(self.stat_attrs(st, path))
 | 
	
		
			
				|  |  |          self.items.append(item)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def process_chunk2(self, id, cache):
 |