1 |
The xattrs are preserved in pax headers, in the same way that GNU tar |
2 |
preserves them. |
3 |
|
4 |
X-Gentoo-Bug: 550006 |
5 |
X-Gentoo-Bug-url: https://bugs.gentoo.org/show_bug.cgi?id=550006 |
6 |
--- |
7 |
bin/quickpkg | 16 ++++++++++++++-- |
8 |
pym/portage/dbapi/vartree.py | 18 +++++++++++++++--- |
9 |
pym/portage/util/xattr.py | 18 ++++++++++++++++++ |
10 |
3 files changed, 47 insertions(+), 5 deletions(-) |
11 |
create mode 100644 pym/portage/util/xattr.py |
12 |
|
13 |
diff --git a/bin/quickpkg b/bin/quickpkg |
14 |
index 8b71c3e..726abff 100755 |
15 |
--- a/bin/quickpkg |
16 |
+++ b/bin/quickpkg |
17 |
@@ -22,6 +22,7 @@ from portage.dep import Atom, use_reduce |
18 |
from portage.exception import (AmbiguousPackageName, InvalidAtom, InvalidData, |
19 |
InvalidDependString, PackageSetNotFound, PermissionDenied) |
20 |
from portage.util import ConfigProtect, ensure_dirs, shlex_split |
21 |
+import portage.util.xattr as _xattr |
22 |
from portage.dbapi.vartree import dblink, tar_contents |
23 |
from portage.checksum import perform_md5 |
24 |
from portage._sets import load_default_config, SETPREFIX |
25 |
@@ -35,6 +36,7 @@ def quickpkg_atom(options, infos, arg, eout): |
26 |
vartree = trees["vartree"] |
27 |
vardb = vartree.dbapi |
28 |
bintree = trees["bintree"] |
29 |
+ xattr = 'xattr' in settings.features |
30 |
|
31 |
include_config = options.include_config == "y" |
32 |
include_unmodified_config = options.include_unmodified_config == "y" |
33 |
@@ -132,8 +134,11 @@ def quickpkg_atom(options, infos, arg, eout): |
34 |
binpkg_tmpfile = os.path.join(bintree.pkgdir, |
35 |
cpv + ".tbz2." + str(os.getpid())) |
36 |
ensure_dirs(os.path.dirname(binpkg_tmpfile)) |
37 |
- tar = tarfile.open(binpkg_tmpfile, "w:bz2") |
38 |
- tar_contents(contents, root, tar, protect=protect) |
39 |
+ # The tarfile module will write pax headers holding the |
40 |
+ # xattrs only if PAX_FORMAT is specified here. |
41 |
+ tar = tarfile.open(binpkg_tmpfile, "w:bz2", |
42 |
+ format=tarfile.PAX_FORMAT if xattr else tarfile.DEFAULT_FORMAT) |
43 |
+ tar_contents(contents, root, tar, protect=protect, xattr=xattr) |
44 |
tar.close() |
45 |
xpak.tbz2(binpkg_tmpfile).recompose_mem(xpdata) |
46 |
finally: |
47 |
@@ -233,6 +238,13 @@ def quickpkg_main(options, args, eout): |
48 |
eout.eerror("No write access to '%s'" % bintree.pkgdir) |
49 |
return errno.EACCES |
50 |
|
51 |
+ if 'xattr' in portage.settings.features and not hasattr(_xattr, 'getxattr'): |
52 |
+ eout.eerror("No xattr support library was found, " |
53 |
+ "so xattrs will not be preserved!") |
54 |
+ portage.settings.unlock() |
55 |
+ portage.settings.features.remove('xattr') |
56 |
+ portage.settings.lock() |
57 |
+ |
58 |
infos = {} |
59 |
infos["successes"] = [] |
60 |
infos["missing"] = [] |
61 |
diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py |
62 |
index a2fb325..62d880e 100644 |
63 |
--- a/pym/portage/dbapi/vartree.py |
64 |
+++ b/pym/portage/dbapi/vartree.py |
65 |
@@ -35,6 +35,7 @@ portage.proxy.lazyimport.lazyimport(globals(), |
66 |
'portage.util.movefile:movefile', |
67 |
'portage.util.path:first_existing,iter_parents', |
68 |
'portage.util.writeable_check:get_ro_checker', |
69 |
+ 'portage.util:xattr@_xattr', |
70 |
'portage.util._dyn_libs.PreservedLibsRegistry:PreservedLibsRegistry', |
71 |
'portage.util._dyn_libs.LinkageMapELF:LinkageMapELF@LinkageMap', |
72 |
'portage.util._async.SchedulerInterface:SchedulerInterface', |
73 |
@@ -5266,7 +5267,8 @@ def write_contents(contents, root, f): |
74 |
line = "%s %s\n" % (entry_type, relative_filename) |
75 |
f.write(line) |
76 |
|
77 |
-def tar_contents(contents, root, tar, protect=None, onProgress=None): |
78 |
+def tar_contents(contents, root, tar, protect=None, onProgress=None, |
79 |
+ xattr=False): |
80 |
os = _os_merge |
81 |
encoding = _encodings['merge'] |
82 |
|
83 |
@@ -5384,9 +5386,19 @@ def tar_contents(contents, root, tar, protect=None, onProgress=None): |
84 |
tar.addfile(tarinfo, f) |
85 |
f.close() |
86 |
else: |
87 |
- with open(_unicode_encode(path, |
88 |
+ path_bytes = _unicode_encode(path, |
89 |
encoding=encoding, |
90 |
- errors='strict'), 'rb') as f: |
91 |
+ errors='strict') |
92 |
+ |
93 |
+ if xattr: |
94 |
+ # Compatible with GNU tar, which saves the xattrs |
95 |
+ # under the SCHILY.xattr namespace. |
96 |
+ for k in _xattr.listxattr(path_bytes): |
97 |
+ tarinfo.pax_headers['SCHILY.xattr.' + |
98 |
+ _unicode_decode(k)] = _unicode_decode( |
99 |
+ _xattr.getxattr(path_bytes, _unicode_encode(k))) |
100 |
+ |
101 |
+ with open(path_bytes, 'rb') as f: |
102 |
tar.addfile(tarinfo, f) |
103 |
|
104 |
else: |
105 |
diff --git a/pym/portage/util/xattr.py b/pym/portage/util/xattr.py |
106 |
new file mode 100644 |
107 |
index 0000000..0f7ab6f |
108 |
--- /dev/null |
109 |
+++ b/pym/portage/util/xattr.py |
110 |
@@ -0,0 +1,18 @@ |
111 |
+# Copyright 2015 Gentoo Foundation |
112 |
+# Distributed under the terms of the GNU General Public License v2 |
113 |
+ |
114 |
+import os as _os |
115 |
+ |
116 |
+if hasattr(_os, "getxattr"): |
117 |
+ getxattr = _os.getxattr |
118 |
+ listxattr = _os.listxattr |
119 |
+ setxattr = _os.setxattr |
120 |
+else: |
121 |
+ try: |
122 |
+ import xattr as _xattr |
123 |
+ except ImportError: |
124 |
+ pass |
125 |
+ else: |
126 |
+ getxattr = _xattr.get |
127 |
+ listxattr = _xattr.list |
128 |
+ setxattr = _xattr.set |
129 |
-- |
130 |
2.3.5 |