1 |
commit: 655c8668bc561a3b17c5b5490480bd15e611412b |
2 |
Author: Zac Medico <zmedico <AT> gentoo <DOT> org> |
3 |
AuthorDate: Wed Mar 27 08:21:46 2013 +0000 |
4 |
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> |
5 |
CommitDate: Wed Mar 27 08:21:46 2013 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=655c8668 |
7 |
|
8 |
PORTAGE_XATTR_EXCLUDE="security.*", bug #461868 |
9 |
|
10 |
--- |
11 |
cnf/make.globals | 5 +- |
12 |
man/make.conf.5 | 11 +++- |
13 |
.../package/ebuild/_config/special_env_vars.py | 3 +- |
14 |
pym/portage/util/movefile.py | 75 ++++++++++++++++++-- |
15 |
4 files changed, 83 insertions(+), 11 deletions(-) |
16 |
|
17 |
diff --git a/cnf/make.globals b/cnf/make.globals |
18 |
index 80a68f7..f0597c1 100644 |
19 |
--- a/cnf/make.globals |
20 |
+++ b/cnf/make.globals |
21 |
@@ -1,4 +1,4 @@ |
22 |
-# Copyright 1999-2011 Gentoo Foundation |
23 |
+# Copyright 1999-2013 Gentoo Foundation |
24 |
# Distributed under the terms of the GNU General Public License v2 |
25 |
# System-wide defaults for the Portage system |
26 |
|
27 |
@@ -123,6 +123,9 @@ PORTAGE_ELOG_MAILFROM="portage@localhost" |
28 |
# Signing command used by repoman |
29 |
PORTAGE_GPG_SIGNING_COMMAND="gpg --sign --digest-algo SHA256 --clearsign --yes --default-key \"\${PORTAGE_GPG_KEY}\" --homedir \"\${PORTAGE_GPG_DIR}\" \"\${FILE}\"" |
30 |
|
31 |
+# Security labels are special, see bug #461868. |
32 |
+PORTAGE_XATTR_EXCLUDE="security.*" |
33 |
+ |
34 |
# ***************************** |
35 |
# ** DO NOT EDIT THIS FILE ** |
36 |
# *************************************************** |
37 |
|
38 |
diff --git a/man/make.conf.5 b/man/make.conf.5 |
39 |
index 42a5b25..5e35546 100644 |
40 |
--- a/man/make.conf.5 |
41 |
+++ b/man/make.conf.5 |
42 |
@@ -1,4 +1,4 @@ |
43 |
-.TH "MAKE.CONF" "5" "Jan 2013" "Portage VERSION" "Portage" |
44 |
+.TH "MAKE.CONF" "5" "Mar 2013" "Portage VERSION" "Portage" |
45 |
.SH "NAME" |
46 |
make.conf \- custom settings for Portage |
47 |
.SH "SYNOPSIS" |
48 |
@@ -573,7 +573,8 @@ Enable GPG verification when using \fIemerge\-webrsync\fR. |
49 |
.TP |
50 |
.B xattr |
51 |
Preserve extended attributes (filesystem-stored metadata) when installing |
52 |
-files (see \fBattr\fR(1)). |
53 |
+files (see \fBattr\fR(1)). The \fBPORTAGE_XATTR_EXCLUDE\fR variable may be |
54 |
+used to exclude specific attributes from being preserved. |
55 |
.RE |
56 |
.TP |
57 |
.B FETCHCOMMAND |
58 |
@@ -859,6 +860,12 @@ Defaults to portage. |
59 |
\fBPORTAGE_WORKDIR_MODE\fR = \fI"0700"\fR |
60 |
This variable controls permissions for \fIWORKDIR\fR (see \fBebuild\fR(5)). |
61 |
.TP |
62 |
+\fBPORTAGE_XATTR_EXCLUDE\fR = \fI[space delimited list of fnmatch patterns]\fR |
63 |
+This variable may be used to exclude specific attributes from being preserved |
64 |
+when \fBxattr\fR is in \fBFEATURES\fR. |
65 |
+.br |
66 |
+Defaults to "security.*" (security labels are special, see bug #461868). |
67 |
+.TP |
68 |
\fBPORTDIR\fR = \fI[path]\fR |
69 |
Defines the location of the Portage tree. This is the repository for all |
70 |
profile information as well as all ebuilds. If you change this, you must update |
71 |
|
72 |
diff --git a/pym/portage/package/ebuild/_config/special_env_vars.py b/pym/portage/package/ebuild/_config/special_env_vars.py |
73 |
index 8e85a46..0b4dc39 100644 |
74 |
--- a/pym/portage/package/ebuild/_config/special_env_vars.py |
75 |
+++ b/pym/portage/package/ebuild/_config/special_env_vars.py |
76 |
@@ -170,7 +170,8 @@ environ_filter += [ |
77 |
"PORTAGE_RO_DISTDIRS", |
78 |
"PORTAGE_RSYNC_EXTRA_OPTS", "PORTAGE_RSYNC_OPTS", |
79 |
"PORTAGE_RSYNC_RETRIES", "PORTAGE_SYNC_STALE", |
80 |
- "PORTAGE_USE", "PORT_LOGDIR", "PORT_LOGDIR_CLEAN", |
81 |
+ "PORTAGE_USE", "PORTAGE_XATTR_EXCLUDE", |
82 |
+ "PORT_LOGDIR", "PORT_LOGDIR_CLEAN", |
83 |
"QUICKPKG_DEFAULT_OPTS", "REPOMAN_DEFAULT_OPTS", |
84 |
"RESUMECOMMAND", "RESUMECOMMAND_FTP", |
85 |
"RESUMECOMMAND_HTTP", "RESUMECOMMAND_HTTPS", |
86 |
|
87 |
diff --git a/pym/portage/util/movefile.py b/pym/portage/util/movefile.py |
88 |
index bf95f1a..8a7a2b6 100644 |
89 |
--- a/pym/portage/util/movefile.py |
90 |
+++ b/pym/portage/util/movefile.py |
91 |
@@ -6,6 +6,7 @@ from __future__ import unicode_literals |
92 |
__all__ = ['movefile'] |
93 |
|
94 |
import errno |
95 |
+import fnmatch |
96 |
import os as _os |
97 |
import shutil as _shutil |
98 |
import stat |
99 |
@@ -27,10 +28,59 @@ def _apply_stat(src_stat, dest): |
100 |
_os.chown(dest, src_stat.st_uid, src_stat.st_gid) |
101 |
_os.chmod(dest, stat.S_IMODE(src_stat.st_mode)) |
102 |
|
103 |
+_xattr_excluder_cache = {} |
104 |
+ |
105 |
+def _get_xattr_excluder(pattern): |
106 |
+ |
107 |
+ try: |
108 |
+ value = _xattr_excluder_cache[pattern] |
109 |
+ except KeyError: |
110 |
+ value = _xattr_excluder(pattern) |
111 |
+ _xattr_excluder_cache[pattern] = value |
112 |
+ |
113 |
+ return value |
114 |
+ |
115 |
+class _xattr_excluder(object): |
116 |
+ |
117 |
+ __slots__ = ('_pattern_split',) |
118 |
+ |
119 |
+ def __init__(self, pattern): |
120 |
+ |
121 |
+ if pattern is None: |
122 |
+ self._pattern_split = None |
123 |
+ else: |
124 |
+ pattern = pattern.split() |
125 |
+ if not pattern: |
126 |
+ self._pattern_split = None |
127 |
+ else: |
128 |
+ pattern.sort() |
129 |
+ self._pattern_split = tuple(pattern) |
130 |
+ |
131 |
+ def __call__(self, attr): |
132 |
+ |
133 |
+ if self._pattern_split is None: |
134 |
+ return False |
135 |
+ |
136 |
+ match = fnmatch.fnmatch |
137 |
+ for x in self._pattern_split: |
138 |
+ if match(attr, x): |
139 |
+ return True |
140 |
+ |
141 |
+ return False |
142 |
+ |
143 |
if hasattr(_os, "getxattr"): |
144 |
# Python >=3.3 and GNU/Linux |
145 |
- def _copyxattr(src, dest): |
146 |
- for attr in _os.listxattr(src): |
147 |
+ def _copyxattr(src, dest, exclude=None): |
148 |
+ |
149 |
+ attrs = _os.listxattr(src) |
150 |
+ if attrs: |
151 |
+ if exclude is not None and isinstance(attrs[0], bytes): |
152 |
+ exclude = exclude.encode(_encodings['fs']) |
153 |
+ exclude = _get_xattr_excluder(exclude) |
154 |
+ |
155 |
+ for attr in attrs: |
156 |
+ if exclude(attr): |
157 |
+ continue |
158 |
try: |
159 |
_os.setxattr(dest, attr, _os.getxattr(src, attr)) |
160 |
raise_exception = False |
161 |
@@ -44,8 +94,17 @@ else: |
162 |
except ImportError: |
163 |
xattr = None |
164 |
if xattr is not None: |
165 |
- def _copyxattr(src, dest): |
166 |
- for attr in xattr.list(src): |
167 |
+ def _copyxattr(src, dest, exclude=None): |
168 |
+ |
169 |
+ attrs = xattr.list(src) |
170 |
+ if attrs: |
171 |
+ if exclude is not None and isinstance(attrs[0], bytes): |
172 |
+ exclude = exclude.encode(_encodings['fs']) |
173 |
+ exclude = _get_xattr_excluder(exclude) |
174 |
+ |
175 |
+ for attr in attrs: |
176 |
+ if exclude(attr): |
177 |
+ continue |
178 |
try: |
179 |
xattr.set(dest, attr, xattr.get(src, attr)) |
180 |
raise_exception = False |
181 |
@@ -63,7 +122,8 @@ else: |
182 |
_has_getfattr_and_setfattr = False |
183 |
_devnull.close() |
184 |
if _has_getfattr_and_setfattr: |
185 |
- def _copyxattr(src, dest): |
186 |
+ def _copyxattr(src, dest, exclude=None): |
187 |
+ # TODO: implement exclude |
188 |
getfattr_process = subprocess.Popen(["getfattr", "-d", "--absolute-names", src], stdout=subprocess.PIPE) |
189 |
getfattr_process.wait() |
190 |
extended_attributes = getfattr_process.stdout.readlines() |
191 |
@@ -75,7 +135,7 @@ else: |
192 |
if setfattr_process.returncode != 0: |
193 |
raise OperationNotSupported("Filesystem containing file '%s' does not support extended attributes" % dest) |
194 |
else: |
195 |
- def _copyxattr(src, dest): |
196 |
+ def _copyxattr(src, dest, exclude=None): |
197 |
pass |
198 |
|
199 |
def movefile(src, dest, newmtime=None, sstat=None, mysettings=None, |
200 |
@@ -246,7 +306,8 @@ def movefile(src, dest, newmtime=None, sstat=None, mysettings=None, |
201 |
_copyfile(src_bytes, dest_tmp_bytes) |
202 |
if xattr_enabled: |
203 |
try: |
204 |
- _copyxattr(src_bytes, dest_tmp_bytes) |
205 |
+ _copyxattr(src_bytes, dest_tmp_bytes, |
206 |
+ exclude=mysettings.get("PORTAGE_XATTR_EXCLUDE", "security.*")) |
207 |
except SystemExit: |
208 |
raise |
209 |
except: |