Gentoo Archives: gentoo-commits

From: "Zac Medico (zmedico)" <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r15448 - in main/trunk/pym: _emerge portage portage/dbapi portage/package/ebuild portage/tests/ebuild
Date: Thu, 25 Feb 2010 03:37:43
Message-Id: E1NkUXb-0006HL-N0@stork.gentoo.org
1 Author: zmedico
2 Date: 2010-02-25 03:37:29 +0000 (Thu, 25 Feb 2010)
3 New Revision: 15448
4
5 Added:
6 main/trunk/pym/portage/package/ebuild/_pty.py
7 main/trunk/pym/portage/package/ebuild/doebuild.py
8 main/trunk/pym/portage/package/ebuild/prepare_build_dirs.py
9 Modified:
10 main/trunk/pym/_emerge/AbstractEbuildProcess.py
11 main/trunk/pym/_emerge/EbuildFetcher.py
12 main/trunk/pym/_emerge/EbuildPhase.py
13 main/trunk/pym/_emerge/EbuildProcess.py
14 main/trunk/pym/_emerge/MiscFunctionsProcess.py
15 main/trunk/pym/portage/__init__.py
16 main/trunk/pym/portage/dbapi/bintree.py
17 main/trunk/pym/portage/dbapi/vartree.py
18 main/trunk/pym/portage/package/ebuild/fetch.py
19 main/trunk/pym/portage/tests/ebuild/test_pty_eof.py
20 Log:
21 Split doebuild and related code to the portage.package.ebuild module.
22
23
24 Modified: main/trunk/pym/_emerge/AbstractEbuildProcess.py
25 ===================================================================
26 --- main/trunk/pym/_emerge/AbstractEbuildProcess.py 2010-02-24 21:27:43 UTC (rev 15447)
27 +++ main/trunk/pym/_emerge/AbstractEbuildProcess.py 2010-02-25 03:37:29 UTC (rev 15448)
28 @@ -5,6 +5,7 @@
29 from _emerge.SpawnProcess import SpawnProcess
30 import portage
31 from portage import os
32 +from portage.package.ebuild._pty import _create_pty_or_pipe
33
34 class AbstractEbuildProcess(SpawnProcess):
35
36 @@ -13,7 +14,7 @@
37 def _pipe(self, fd_pipes):
38 stdout_pipe = fd_pipes.get(1)
39 got_pty, master_fd, slave_fd = \
40 - portage._create_pty_or_pipe(copy_term_size=stdout_pipe)
41 + _create_pty_or_pipe(copy_term_size=stdout_pipe)
42 return (master_fd, slave_fd)
43
44 def _can_log(self, slave_fd):
45
46 Modified: main/trunk/pym/_emerge/EbuildFetcher.py
47 ===================================================================
48 --- main/trunk/pym/_emerge/EbuildFetcher.py 2010-02-24 21:27:43 UTC (rev 15447)
49 +++ main/trunk/pym/_emerge/EbuildFetcher.py 2010-02-25 03:37:29 UTC (rev 15448)
50 @@ -11,6 +11,7 @@
51 from portage import _unicode_encode
52 import codecs
53 from portage.elog.messages import eerror
54 +from portage.package.ebuild._pty import _create_pty_or_pipe
55
56 class EbuildFetcher(SpawnProcess):
57
58 @@ -142,7 +143,7 @@
59 return os.pipe()
60 stdout_pipe = fd_pipes.get(1)
61 got_pty, master_fd, slave_fd = \
62 - portage._create_pty_or_pipe(copy_term_size=stdout_pipe)
63 + _create_pty_or_pipe(copy_term_size=stdout_pipe)
64 return (master_fd, slave_fd)
65
66 def _set_returncode(self, wait_retval):
67
68 Modified: main/trunk/pym/_emerge/EbuildPhase.py
69 ===================================================================
70 --- main/trunk/pym/_emerge/EbuildPhase.py 2010-02-24 21:27:43 UTC (rev 15447)
71 +++ main/trunk/pym/_emerge/EbuildPhase.py 2010-02-25 03:37:29 UTC (rev 15448)
72 @@ -5,6 +5,9 @@
73 from _emerge.MiscFunctionsProcess import MiscFunctionsProcess
74 from _emerge.EbuildProcess import EbuildProcess
75 from _emerge.CompositeTask import CompositeTask
76 +from portage.package.ebuild.doebuild import _check_build_log, \
77 + _post_phase_cmds, _post_src_install_chost_fix, \
78 + _post_src_install_uid_fix
79 from portage.util import writemsg, writemsg_stdout
80 import portage
81 from portage import os
82 @@ -18,8 +21,6 @@
83 __slots__ = ("background", "pkg", "phase",
84 "scheduler", "settings", "tree")
85
86 - _post_phase_cmds = portage._post_phase_cmds
87 -
88 def _start(self):
89
90 ebuild_process = EbuildProcess(background=self.background,
91 @@ -39,7 +40,7 @@
92 encoding=_encodings['fs'], errors='strict'),
93 mode='a', encoding=_encodings['content'], errors='replace')
94 try:
95 - portage._check_build_log(self.settings, out=out)
96 + _check_build_log(self.settings, out=out)
97 msg = _unicode_decode(out.getvalue(),
98 encoding=_encodings['content'], errors='replace')
99 if msg:
100 @@ -66,12 +67,12 @@
101 encoding=_encodings['fs'], errors='strict'),
102 mode='a', encoding=_encodings['content'], errors='replace')
103 out = log_file
104 - portage._post_src_install_chost_fix(settings)
105 - portage._post_src_install_uid_fix(settings, out=out)
106 + _post_src_install_chost_fix(settings)
107 + _post_src_install_uid_fix(settings, out=out)
108 if log_file is not None:
109 log_file.close()
110
111 - post_phase_cmds = self._post_phase_cmds.get(self.phase)
112 + post_phase_cmds = _post_phase_cmds.get(self.phase)
113 if post_phase_cmds is not None:
114 post_phase = MiscFunctionsProcess(background=self.background,
115 commands=post_phase_cmds, phase=self.phase, pkg=self.pkg,
116
117 Modified: main/trunk/pym/_emerge/EbuildProcess.py
118 ===================================================================
119 --- main/trunk/pym/_emerge/EbuildProcess.py 2010-02-24 21:27:43 UTC (rev 15447)
120 +++ main/trunk/pym/_emerge/EbuildProcess.py 2010-02-25 03:37:29 UTC (rev 15448)
121 @@ -3,8 +3,9 @@
122 # $Id$
123
124 from _emerge.AbstractEbuildProcess import AbstractEbuildProcess
125 -import portage
126 from portage import os
127 +from portage.package.ebuild.doebuild import doebuild, \
128 + _doebuild_exit_status_check_and_log, _post_phase_userpriv_perms
129
130 class EbuildProcess(AbstractEbuildProcess):
131
132 @@ -26,8 +27,9 @@
133 settings = self.settings
134 ebuild_path = settings["EBUILD"]
135 debug = settings.get("PORTAGE_DEBUG") == "1"
136 +
137
138 - rval = portage.doebuild(ebuild_path, self.phase,
139 + rval = doebuild(ebuild_path, self.phase,
140 root_config.root, settings, debug,
141 mydbapi=mydbapi, tree=tree, **kwargs)
142
143 @@ -37,12 +39,12 @@
144 AbstractEbuildProcess._set_returncode(self, wait_retval)
145
146 if self.phase not in ("clean", "cleanrm"):
147 - self.returncode = portage._doebuild_exit_status_check_and_log(
148 + self.returncode = _doebuild_exit_status_check_and_log(
149 self.settings, self.phase, self.returncode)
150
151 if self.phase == "test" and self.returncode != os.EX_OK and \
152 "test-fail-continue" in self.settings.features:
153 self.returncode = os.EX_OK
154
155 - portage._post_phase_userpriv_perms(self.settings)
156 + _post_phase_userpriv_perms(self.settings)
157
158
159 Modified: main/trunk/pym/_emerge/MiscFunctionsProcess.py
160 ===================================================================
161 --- main/trunk/pym/_emerge/MiscFunctionsProcess.py 2010-02-24 21:27:43 UTC (rev 15447)
162 +++ main/trunk/pym/_emerge/MiscFunctionsProcess.py 2010-02-25 03:37:29 UTC (rev 15448)
163 @@ -5,6 +5,8 @@
164 from _emerge.AbstractEbuildProcess import AbstractEbuildProcess
165 import portage
166 from portage import os
167 +from portage.package.ebuild.doebuild import spawn, \
168 + _doebuild_exit_status_check_and_log, _doebuild_exit_status_unlink
169
170 class MiscFunctionsProcess(AbstractEbuildProcess):
171 """
172 @@ -23,7 +25,7 @@
173 self.args = [portage._shell_quote(misc_sh_binary)] + self.commands
174 self.logfile = settings.get("PORTAGE_LOG_FILE")
175
176 - portage._doebuild_exit_status_unlink(
177 + _doebuild_exit_status_unlink(
178 settings.get("EBUILD_EXIT_STATUS_FILE"))
179
180 AbstractEbuildProcess._start(self)
181 @@ -31,11 +33,11 @@
182 def _spawn(self, args, **kwargs):
183 settings = self.settings
184 debug = settings.get("PORTAGE_DEBUG") == "1"
185 - return portage.spawn(" ".join(args), settings,
186 + return spawn(" ".join(args), settings,
187 debug=debug, **kwargs)
188
189 def _set_returncode(self, wait_retval):
190 AbstractEbuildProcess._set_returncode(self, wait_retval)
191 - self.returncode = portage._doebuild_exit_status_check_and_log(
192 + self.returncode = _doebuild_exit_status_check_and_log(
193 self.settings, self.phase, self.returncode)
194
195
196 Modified: main/trunk/pym/portage/__init__.py
197 ===================================================================
198 --- main/trunk/pym/portage/__init__.py 2010-02-24 21:27:43 UTC (rev 15447)
199 +++ main/trunk/pym/portage/__init__.py 2010-02-25 03:37:29 UTC (rev 15448)
200 @@ -102,9 +102,12 @@
201 'portage.manifest:Manifest',
202 'portage.output',
203 'portage.output:bold,colorize',
204 + 'portage.package.ebuild.doebuild:doebuild,' + \
205 + 'doebuild_environment,spawn,spawnebuild',
206 'portage.package.ebuild.config:autouse,best_from_dict,' + \
207 'check_config_instance,config',
208 'portage.package.ebuild.fetch:fetch',
209 + 'portage.package.ebuild.prepare_build_dirs:prepare_build_dirs',
210 'portage.process',
211 'portage.process:atexit_register,run_exitfuncs',
212 'portage.update:dep_transform,fixdbentries,grab_updates,' + \
213 @@ -997,385 +1000,6 @@
214
215 return (version,None)
216
217 -def _can_test_pty_eof():
218 - """
219 - The _test_pty_eof() function seems to hang on most
220 - kernels other than Linux.
221 - This was reported for the following kernels which used to work fine
222 - without this EOF test: Darwin, AIX, FreeBSD. They seem to hang on
223 - the slave_file.close() call. Note that Python's implementation of
224 - openpty on Solaris already caused random hangs without this EOF test
225 - and hence is globally disabled.
226 - @rtype: bool
227 - @returns: True if _test_pty_eof() won't hang, False otherwise.
228 - """
229 - return platform.system() in ("Linux",)
230 -
231 -def _test_pty_eof():
232 - """
233 - Returns True if this issues is fixed for the currently
234 - running version of python: http://bugs.python.org/issue5380
235 - Raises an EnvironmentError from openpty() if it fails.
236 - """
237 -
238 - use_fork = False
239 -
240 - import array, fcntl, pty, select, termios
241 - test_string = 2 * "blah blah blah\n"
242 - test_string = _unicode_decode(test_string,
243 - encoding='utf_8', errors='strict')
244 -
245 - # may raise EnvironmentError
246 - master_fd, slave_fd = pty.openpty()
247 -
248 - # Non-blocking mode is required for Darwin kernel.
249 - fcntl.fcntl(master_fd, fcntl.F_SETFL,
250 - fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
251 -
252 - # Disable post-processing of output since otherwise weird
253 - # things like \n -> \r\n transformations may occur.
254 - mode = termios.tcgetattr(slave_fd)
255 - mode[1] &= ~termios.OPOST
256 - termios.tcsetattr(slave_fd, termios.TCSANOW, mode)
257 -
258 - # Simulate a subprocess writing some data to the
259 - # slave end of the pipe, and then exiting.
260 - pid = None
261 - if use_fork:
262 - pids = process.spawn_bash(_unicode_encode("echo -n '%s'" % test_string,
263 - encoding='utf_8', errors='strict'), env=os.environ,
264 - fd_pipes={0:sys.stdin.fileno(), 1:slave_fd, 2:slave_fd},
265 - returnpid=True)
266 - if isinstance(pids, int):
267 - os.close(master_fd)
268 - os.close(slave_fd)
269 - raise EnvironmentError('spawn failed')
270 - pid = pids[0]
271 - else:
272 - os.write(slave_fd, _unicode_encode(test_string,
273 - encoding='utf_8', errors='strict'))
274 - os.close(slave_fd)
275 -
276 - # If using a fork, we must wait for the child here,
277 - # in order to avoid a race condition that would
278 - # lead to inconsistent results.
279 - if pid is not None:
280 - os.waitpid(pid, 0)
281 -
282 - master_file = os.fdopen(master_fd, 'rb')
283 - eof = False
284 - data = []
285 - iwtd = [master_file]
286 - owtd = []
287 - ewtd = []
288 -
289 - while not eof:
290 -
291 - events = select.select(iwtd, owtd, ewtd)
292 - if not events[0]:
293 - eof = True
294 - break
295 -
296 - buf = array.array('B')
297 - try:
298 - buf.fromfile(master_file, 1024)
299 - except EOFError:
300 - eof = True
301 - except IOError:
302 - # This is where data loss occurs.
303 - eof = True
304 -
305 - if not buf:
306 - eof = True
307 - else:
308 - data.append(_unicode_decode(buf.tostring(),
309 - encoding='utf_8', errors='strict'))
310 -
311 - master_file.close()
312 -
313 - return test_string == ''.join(data)
314 -
315 -# If _test_pty_eof() can't be used for runtime detection of
316 -# http://bugs.python.org/issue5380, openpty can't safely be used
317 -# unless we can guarantee that the current version of python has
318 -# been fixed (affects all current versions of python3). When
319 -# this issue is fixed in python3, we can add another sys.hexversion
320 -# conditional to enable openpty support in the fixed versions.
321 -if sys.hexversion >= 0x3000000 and not _can_test_pty_eof():
322 - _disable_openpty = True
323 -else:
324 - # Disable the use of openpty on Solaris as it seems Python's openpty
325 - # implementation doesn't play nice on Solaris with Portage's
326 - # behaviour causing hangs/deadlocks.
327 - # Additional note for the future: on Interix, pipes do NOT work, so
328 - # _disable_openpty on Interix must *never* be True
329 - _disable_openpty = platform.system() in ("SunOS",)
330 -_tested_pty = False
331 -
332 -if not _can_test_pty_eof():
333 - # Skip _test_pty_eof() on systems where it hangs.
334 - _tested_pty = True
335 -
336 -def _create_pty_or_pipe(copy_term_size=None):
337 - """
338 - Try to create a pty and if then fails then create a normal
339 - pipe instead.
340 -
341 - @param copy_term_size: If a tty file descriptor is given
342 - then the term size will be copied to the pty.
343 - @type copy_term_size: int
344 - @rtype: tuple
345 - @returns: A tuple of (is_pty, master_fd, slave_fd) where
346 - is_pty is True if a pty was successfully allocated, and
347 - False if a normal pipe was allocated.
348 - """
349 -
350 - got_pty = False
351 -
352 - global _disable_openpty, _tested_pty
353 - if not (_tested_pty or _disable_openpty):
354 - try:
355 - if not _test_pty_eof():
356 - _disable_openpty = True
357 - except EnvironmentError as e:
358 - _disable_openpty = True
359 - writemsg("openpty failed: '%s'\n" % str(e),
360 - noiselevel=-1)
361 - del e
362 - _tested_pty = True
363 -
364 - if _disable_openpty:
365 - master_fd, slave_fd = os.pipe()
366 - else:
367 - from pty import openpty
368 - try:
369 - master_fd, slave_fd = openpty()
370 - got_pty = True
371 - except EnvironmentError as e:
372 - _disable_openpty = True
373 - writemsg("openpty failed: '%s'\n" % str(e),
374 - noiselevel=-1)
375 - del e
376 - master_fd, slave_fd = os.pipe()
377 -
378 - if got_pty:
379 - # Disable post-processing of output since otherwise weird
380 - # things like \n -> \r\n transformations may occur.
381 - import termios
382 - mode = termios.tcgetattr(slave_fd)
383 - mode[1] &= ~termios.OPOST
384 - termios.tcsetattr(slave_fd, termios.TCSANOW, mode)
385 -
386 - if got_pty and \
387 - copy_term_size is not None and \
388 - os.isatty(copy_term_size):
389 - from portage.output import get_term_size, set_term_size
390 - rows, columns = get_term_size()
391 - set_term_size(rows, columns, slave_fd)
392 -
393 - return (got_pty, master_fd, slave_fd)
394 -
395 -# XXX This would be to replace getstatusoutput completely.
396 -# XXX Issue: cannot block execution. Deadlock condition.
397 -def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakeroot=0, **keywords):
398 - """
399 - Spawn a subprocess with extra portage-specific options.
400 - Optiosn include:
401 -
402 - Sandbox: Sandbox means the spawned process will be limited in its ability t
403 - read and write files (normally this means it is restricted to ${D}/)
404 - SElinux Sandbox: Enables sandboxing on SElinux
405 - Reduced Privileges: Drops privilages such that the process runs as portage:portage
406 - instead of as root.
407 -
408 - Notes: os.system cannot be used because it messes with signal handling. Instead we
409 - use the portage.process spawn* family of functions.
410 -
411 - This function waits for the process to terminate.
412 -
413 - @param mystring: Command to run
414 - @type mystring: String
415 - @param mysettings: Either a Dict of Key,Value pairs or an instance of portage.config
416 - @type mysettings: Dictionary or config instance
417 - @param debug: Ignored
418 - @type debug: Boolean
419 - @param free: Enable sandboxing for this process
420 - @type free: Boolean
421 - @param droppriv: Drop to portage:portage when running this command
422 - @type droppriv: Boolean
423 - @param sesandbox: Enable SELinux Sandboxing (toggles a context switch)
424 - @type sesandbox: Boolean
425 - @param fakeroot: Run this command with faked root privileges
426 - @type fakeroot: Boolean
427 - @param keywords: Extra options encoded as a dict, to be passed to spawn
428 - @type keywords: Dictionary
429 - @rtype: Integer
430 - @returns:
431 - 1. The return code of the spawned process.
432 - """
433 -
434 - if isinstance(mysettings, dict):
435 - env=mysettings
436 - keywords["opt_name"]="[ %s ]" % "portage"
437 - else:
438 - check_config_instance(mysettings)
439 - env=mysettings.environ()
440 - if mysettings.mycpv is not None:
441 - keywords["opt_name"] = "[%s]" % mysettings.mycpv
442 - else:
443 - keywords["opt_name"] = "[%s/%s]" % \
444 - (mysettings.get("CATEGORY",""), mysettings.get("PF",""))
445 -
446 - fd_pipes = keywords.get("fd_pipes")
447 - if fd_pipes is None:
448 - fd_pipes = {
449 - 0:sys.stdin.fileno(),
450 - 1:sys.stdout.fileno(),
451 - 2:sys.stderr.fileno(),
452 - }
453 - # In some cases the above print statements don't flush stdout, so
454 - # it needs to be flushed before allowing a child process to use it
455 - # so that output always shows in the correct order.
456 - stdout_filenos = (sys.stdout.fileno(), sys.stderr.fileno())
457 - for fd in fd_pipes.values():
458 - if fd in stdout_filenos:
459 - sys.stdout.flush()
460 - sys.stderr.flush()
461 - break
462 -
463 - # The default policy for the sesandbox domain only allows entry (via exec)
464 - # from shells and from binaries that belong to portage (the number of entry
465 - # points is minimized). The "tee" binary is not among the allowed entry
466 - # points, so it is spawned outside of the sesandbox domain and reads from a
467 - # pseudo-terminal that connects two domains.
468 - logfile = keywords.get("logfile")
469 - mypids = []
470 - master_fd = None
471 - slave_fd = None
472 - fd_pipes_orig = None
473 - got_pty = False
474 - if logfile:
475 - del keywords["logfile"]
476 - if 1 not in fd_pipes or 2 not in fd_pipes:
477 - raise ValueError(fd_pipes)
478 -
479 - got_pty, master_fd, slave_fd = \
480 - _create_pty_or_pipe(copy_term_size=fd_pipes[1])
481 -
482 - if not got_pty and 'sesandbox' in mysettings.features \
483 - and mysettings.selinux_enabled():
484 - # With sesandbox, logging works through a pty but not through a
485 - # normal pipe. So, disable logging if ptys are broken.
486 - # See Bug #162404.
487 - logfile = None
488 - os.close(master_fd)
489 - master_fd = None
490 - os.close(slave_fd)
491 - slave_fd = None
492 -
493 - if logfile:
494 -
495 - fd_pipes.setdefault(0, sys.stdin.fileno())
496 - fd_pipes_orig = fd_pipes.copy()
497 -
498 - # We must set non-blocking mode before we close the slave_fd
499 - # since otherwise the fcntl call can fail on FreeBSD (the child
500 - # process might have already exited and closed slave_fd so we
501 - # have to keep it open in order to avoid FreeBSD potentially
502 - # generating an EAGAIN exception).
503 - import fcntl
504 - fcntl.fcntl(master_fd, fcntl.F_SETFL,
505 - fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
506 -
507 - fd_pipes[0] = fd_pipes_orig[0]
508 - fd_pipes[1] = slave_fd
509 - fd_pipes[2] = slave_fd
510 - keywords["fd_pipes"] = fd_pipes
511 -
512 - features = mysettings.features
513 - # TODO: Enable fakeroot to be used together with droppriv. The
514 - # fake ownership/permissions will have to be converted to real
515 - # permissions in the merge phase.
516 - fakeroot = fakeroot and uid != 0 and portage.process.fakeroot_capable
517 - if droppriv and not uid and portage_gid and portage_uid:
518 - keywords.update({"uid":portage_uid,"gid":portage_gid,
519 - "groups":userpriv_groups,"umask":0o02})
520 - if not free:
521 - free=((droppriv and "usersandbox" not in features) or \
522 - (not droppriv and "sandbox" not in features and \
523 - "usersandbox" not in features and not fakeroot))
524 -
525 - if not free and not (fakeroot or process.sandbox_capable):
526 - free = True
527 -
528 - if free or "SANDBOX_ACTIVE" in os.environ:
529 - keywords["opt_name"] += " bash"
530 - spawn_func = portage.process.spawn_bash
531 - elif fakeroot:
532 - keywords["opt_name"] += " fakeroot"
533 - keywords["fakeroot_state"] = os.path.join(mysettings["T"], "fakeroot.state")
534 - spawn_func = portage.process.spawn_fakeroot
535 - else:
536 - keywords["opt_name"] += " sandbox"
537 - spawn_func = portage.process.spawn_sandbox
538 -
539 - if sesandbox:
540 - spawn_func = selinux.spawn_wrapper(spawn_func,
541 - mysettings["PORTAGE_SANDBOX_T"])
542 -
543 - returnpid = keywords.get("returnpid")
544 - keywords["returnpid"] = True
545 - try:
546 - mypids.extend(spawn_func(mystring, env=env, **keywords))
547 - finally:
548 - if logfile:
549 - os.close(slave_fd)
550 -
551 - if returnpid:
552 - return mypids
553 -
554 - if logfile:
555 - log_file = open(_unicode_encode(logfile), mode='ab')
556 - apply_secpass_permissions(logfile,
557 - uid=portage_uid, gid=portage_gid, mode=0o664)
558 - stdout_file = os.fdopen(os.dup(fd_pipes_orig[1]), 'wb')
559 - master_file = os.fdopen(master_fd, 'rb')
560 - iwtd = [master_file]
561 - owtd = []
562 - ewtd = []
563 - import array, select
564 - buffsize = 65536
565 - eof = False
566 - while not eof:
567 - events = select.select(iwtd, owtd, ewtd)
568 - for f in events[0]:
569 - # Use non-blocking mode to prevent read
570 - # calls from blocking indefinitely.
571 - buf = array.array('B')
572 - try:
573 - buf.fromfile(f, buffsize)
574 - except EOFError:
575 - pass
576 - if not buf:
577 - eof = True
578 - break
579 - if f is master_file:
580 - buf.tofile(stdout_file)
581 - stdout_file.flush()
582 - buf.tofile(log_file)
583 - log_file.flush()
584 - log_file.close()
585 - stdout_file.close()
586 - master_file.close()
587 - pid = mypids[-1]
588 - retval = os.waitpid(pid, 0)[1]
589 - portage.process.spawned_pids.remove(pid)
590 - if retval != os.EX_OK:
591 - if retval & 0xff:
592 - return (retval & 0xff) << 8
593 - return retval >> 8
594 - return retval
595 -
596 def digestgen(myarchives=None, mysettings=None,
597 overwrite=None, manifestonly=None, myportdb=None):
598 """
599 @@ -1719,498 +1343,6 @@
600 return 0
601 return 1
602
603 -# parse actionmap to spawn ebuild with the appropriate args
604 -def spawnebuild(mydo, actionmap, mysettings, debug, alwaysdep=0,
605 - logfile=None, fd_pipes=None, returnpid=False):
606 - if not returnpid and \
607 - (alwaysdep or "noauto" not in mysettings.features):
608 - # process dependency first
609 - if "dep" in actionmap[mydo]:
610 - retval = spawnebuild(actionmap[mydo]["dep"], actionmap,
611 - mysettings, debug, alwaysdep=alwaysdep, logfile=logfile,
612 - fd_pipes=fd_pipes, returnpid=returnpid)
613 - if retval:
614 - return retval
615 -
616 - eapi = mysettings["EAPI"]
617 -
618 - if mydo == "configure" and eapi in ("0", "1"):
619 - return os.EX_OK
620 -
621 - if mydo == "prepare" and eapi in ("0", "1"):
622 - return os.EX_OK
623 -
624 - if mydo == "pretend" and eapi in ("0", "1", "2", "3", "3_pre2"):
625 - return os.EX_OK
626 -
627 - kwargs = actionmap[mydo]["args"]
628 - mysettings["EBUILD_PHASE"] = mydo
629 - _doebuild_exit_status_unlink(
630 - mysettings.get("EBUILD_EXIT_STATUS_FILE"))
631 -
632 - try:
633 - phase_retval = spawn(actionmap[mydo]["cmd"] % mydo,
634 - mysettings, debug=debug, logfile=logfile,
635 - fd_pipes=fd_pipes, returnpid=returnpid, **kwargs)
636 - finally:
637 - mysettings["EBUILD_PHASE"] = ""
638 -
639 - if returnpid:
640 - return phase_retval
641 -
642 - msg = _doebuild_exit_status_check(mydo, mysettings)
643 - if msg:
644 - if phase_retval == os.EX_OK:
645 - phase_retval = 1
646 - from textwrap import wrap
647 - from portage.elog.messages import eerror
648 - for l in wrap(msg, 72):
649 - eerror(l, phase=mydo, key=mysettings.mycpv)
650 -
651 - _post_phase_userpriv_perms(mysettings)
652 - if mydo == "install":
653 - out = StringIO()
654 - _check_build_log(mysettings, out=out)
655 - msg = _unicode_decode(out.getvalue(),
656 - encoding=_encodings['content'], errors='replace')
657 - if msg:
658 - writemsg_stdout(msg, noiselevel=-1)
659 - if logfile is not None:
660 - try:
661 - f = codecs.open(_unicode_encode(logfile,
662 - encoding=_encodings['fs'], errors='strict'),
663 - mode='a', encoding=_encodings['content'],
664 - errors='replace')
665 - except EnvironmentError:
666 - pass
667 - else:
668 - f.write(msg)
669 - f.close()
670 - if phase_retval == os.EX_OK:
671 - _post_src_install_chost_fix(mysettings)
672 - phase_retval = _post_src_install_checks(mysettings)
673 -
674 - if mydo == "test" and phase_retval != os.EX_OK and \
675 - "test-fail-continue" in mysettings.features:
676 - phase_retval = os.EX_OK
677 -
678 - return phase_retval
679 -
680 -_post_phase_cmds = {
681 -
682 - "install" : [
683 - "install_qa_check",
684 - "install_symlink_html_docs"],
685 -
686 - "preinst" : [
687 - "preinst_bsdflags",
688 - "preinst_sfperms",
689 - "preinst_selinux_labels",
690 - "preinst_suid_scan",
691 - "preinst_mask"],
692 -
693 - "postinst" : [
694 - "postinst_bsdflags"]
695 -}
696 -
697 -def _post_phase_userpriv_perms(mysettings):
698 - if "userpriv" in mysettings.features and secpass >= 2:
699 - """ Privileged phases may have left files that need to be made
700 - writable to a less privileged user."""
701 - apply_recursive_permissions(mysettings["T"],
702 - uid=portage_uid, gid=portage_gid, dirmode=0o70, dirmask=0,
703 - filemode=0o60, filemask=0)
704 -
705 -def _post_src_install_checks(mysettings):
706 - _post_src_install_uid_fix(mysettings)
707 - global _post_phase_cmds
708 - retval = _spawn_misc_sh(mysettings, _post_phase_cmds["install"],
709 - phase='internal_post_src_install')
710 - if retval != os.EX_OK:
711 - writemsg(_("!!! install_qa_check failed; exiting.\n"),
712 - noiselevel=-1)
713 - return retval
714 -
715 -def _check_build_log(mysettings, out=None):
716 - """
717 - Search the content of $PORTAGE_LOG_FILE if it exists
718 - and generate the following QA Notices when appropriate:
719 -
720 - * Automake "maintainer mode"
721 - * command not found
722 - * Unrecognized configure options
723 - """
724 - logfile = mysettings.get("PORTAGE_LOG_FILE")
725 - if logfile is None:
726 - return
727 - try:
728 - f = codecs.open(_unicode_encode(logfile,
729 - encoding=_encodings['fs'], errors='strict'),
730 - mode='r', encoding=_encodings['content'], errors='replace')
731 - except EnvironmentError:
732 - return
733 -
734 - am_maintainer_mode = []
735 - bash_command_not_found = []
736 - bash_command_not_found_re = re.compile(
737 - r'(.*): line (\d*): (.*): command not found$')
738 - command_not_found_exclude_re = re.compile(r'/configure: line ')
739 - helper_missing_file = []
740 - helper_missing_file_re = re.compile(
741 - r'^!!! (do|new).*: .* does not exist$')
742 -
743 - configure_opts_warn = []
744 - configure_opts_warn_re = re.compile(
745 - r'^configure: WARNING: [Uu]nrecognized options: ')
746 -
747 - # Exclude output from dev-libs/yaz-3.0.47 which looks like this:
748 - #
749 - #Configuration:
750 - # Automake: ${SHELL} /var/tmp/portage/dev-libs/yaz-3.0.47/work/yaz-3.0.47/config/missing --run automake-1.10
751 - am_maintainer_mode_re = re.compile(r'/missing --run ')
752 - am_maintainer_mode_exclude_re = \
753 - re.compile(r'(/missing --run (autoheader|makeinfo)|^\s*Automake:\s)')
754 -
755 - make_jobserver_re = \
756 - re.compile(r'g?make\[\d+\]: warning: jobserver unavailable:')
757 - make_jobserver = []
758 -
759 - try:
760 - for line in f:
761 - if am_maintainer_mode_re.search(line) is not None and \
762 - am_maintainer_mode_exclude_re.search(line) is None:
763 - am_maintainer_mode.append(line.rstrip("\n"))
764 -
765 - if bash_command_not_found_re.match(line) is not None and \
766 - command_not_found_exclude_re.search(line) is None:
767 - bash_command_not_found.append(line.rstrip("\n"))
768 -
769 - if helper_missing_file_re.match(line) is not None:
770 - helper_missing_file.append(line.rstrip("\n"))
771 -
772 - if configure_opts_warn_re.match(line) is not None:
773 - configure_opts_warn.append(line.rstrip("\n"))
774 -
775 - if make_jobserver_re.match(line) is not None:
776 - make_jobserver.append(line.rstrip("\n"))
777 -
778 - finally:
779 - f.close()
780 -
781 - from portage.elog.messages import eqawarn
782 - def _eqawarn(lines):
783 - for line in lines:
784 - eqawarn(line, phase="install", key=mysettings.mycpv, out=out)
785 - from textwrap import wrap
786 - wrap_width = 70
787 -
788 - if am_maintainer_mode:
789 - msg = [_("QA Notice: Automake \"maintainer mode\" detected:")]
790 - msg.append("")
791 - msg.extend("\t" + line for line in am_maintainer_mode)
792 - msg.append("")
793 - msg.extend(wrap(_(
794 - "If you patch Makefile.am, "
795 - "configure.in, or configure.ac then you "
796 - "should use autotools.eclass and "
797 - "eautomake or eautoreconf. Exceptions "
798 - "are limited to system packages "
799 - "for which it is impossible to run "
800 - "autotools during stage building. "
801 - "See http://www.gentoo.org/p"
802 - "roj/en/qa/autofailure.xml for more information."),
803 - wrap_width))
804 - _eqawarn(msg)
805 -
806 - if bash_command_not_found:
807 - msg = [_("QA Notice: command not found:")]
808 - msg.append("")
809 - msg.extend("\t" + line for line in bash_command_not_found)
810 - _eqawarn(msg)
811 -
812 - if helper_missing_file:
813 - msg = [_("QA Notice: file does not exist:")]
814 - msg.append("")
815 - msg.extend("\t" + line[4:] for line in helper_missing_file)
816 - _eqawarn(msg)
817 -
818 - if configure_opts_warn:
819 - msg = [_("QA Notice: Unrecognized configure options:")]
820 - msg.append("")
821 - msg.extend("\t" + line for line in configure_opts_warn)
822 - _eqawarn(msg)
823 -
824 - if make_jobserver:
825 - msg = [_("QA Notice: make jobserver unavailable:")]
826 - msg.append("")
827 - msg.extend("\t" + line for line in make_jobserver)
828 - _eqawarn(msg)
829 -
830 -def _post_src_install_chost_fix(settings):
831 - """
832 - It's possible that the ebuild has changed the
833 - CHOST variable, so revert it to the initial
834 - setting.
835 - """
836 - if settings.get('CATEGORY') == 'virtual':
837 - return
838 -
839 - chost = settings.get('CHOST')
840 - if chost:
841 - write_atomic(os.path.join(settings['PORTAGE_BUILDDIR'],
842 - 'build-info', 'CHOST'), chost + '\n')
843 -
844 -_vdb_use_conditional_keys = ('DEPEND', 'LICENSE', 'PDEPEND',
845 - 'PROPERTIES', 'PROVIDE', 'RDEPEND', 'RESTRICT',)
846 -_vdb_use_conditional_atoms = frozenset(['DEPEND', 'PDEPEND', 'RDEPEND'])
847 -
848 -def _post_src_install_uid_fix(mysettings, out=None):
849 - """
850 - Files in $D with user and group bits that match the "portage"
851 - user or group are automatically mapped to PORTAGE_INST_UID and
852 - PORTAGE_INST_GID if necessary. The chown system call may clear
853 - S_ISUID and S_ISGID bits, so those bits are restored if
854 - necessary.
855 - """
856 -
857 - os = _os_merge
858 -
859 - inst_uid = int(mysettings["PORTAGE_INST_UID"])
860 - inst_gid = int(mysettings["PORTAGE_INST_GID"])
861 -
862 - if bsd_chflags:
863 - # Temporarily remove all of the flags in order to avoid EPERM errors.
864 - os.system("mtree -c -p %s -k flags > %s" % \
865 - (_shell_quote(mysettings["D"]),
866 - _shell_quote(os.path.join(mysettings["T"], "bsdflags.mtree"))))
867 - os.system("chflags -R noschg,nouchg,nosappnd,nouappnd %s" % \
868 - (_shell_quote(mysettings["D"]),))
869 - os.system("chflags -R nosunlnk,nouunlnk %s 2>/dev/null" % \
870 - (_shell_quote(mysettings["D"]),))
871 -
872 - destdir = mysettings["D"]
873 - unicode_errors = []
874 -
875 - while True:
876 -
877 - unicode_error = False
878 - size = 0
879 - counted_inodes = set()
880 -
881 - for parent, dirs, files in os.walk(destdir):
882 - try:
883 - parent = _unicode_decode(parent,
884 - encoding=_encodings['merge'], errors='strict')
885 - except UnicodeDecodeError:
886 - new_parent = _unicode_decode(parent,
887 - encoding=_encodings['merge'], errors='replace')
888 - new_parent = _unicode_encode(new_parent,
889 - encoding=_encodings['merge'], errors='backslashreplace')
890 - new_parent = _unicode_decode(new_parent,
891 - encoding=_encodings['merge'], errors='replace')
892 - os.rename(parent, new_parent)
893 - unicode_error = True
894 - unicode_errors.append(new_parent[len(destdir):])
895 - break
896 -
897 - for fname in chain(dirs, files):
898 - try:
899 - fname = _unicode_decode(fname,
900 - encoding=_encodings['merge'], errors='strict')
901 - except UnicodeDecodeError:
902 - fpath = _os.path.join(
903 - parent.encode(_encodings['merge']), fname)
904 - new_fname = _unicode_decode(fname,
905 - encoding=_encodings['merge'], errors='replace')
906 - new_fname = _unicode_encode(new_fname,
907 - encoding=_encodings['merge'], errors='backslashreplace')
908 - new_fname = _unicode_decode(new_fname,
909 - encoding=_encodings['merge'], errors='replace')
910 - new_fpath = os.path.join(parent, new_fname)
911 - os.rename(fpath, new_fpath)
912 - unicode_error = True
913 - unicode_errors.append(new_fpath[len(destdir):])
914 - fname = new_fname
915 - fpath = new_fpath
916 - else:
917 - fpath = os.path.join(parent, fname)
918 -
919 - mystat = os.lstat(fpath)
920 - if stat.S_ISREG(mystat.st_mode) and \
921 - mystat.st_ino not in counted_inodes:
922 - counted_inodes.add(mystat.st_ino)
923 - size += mystat.st_size
924 - if mystat.st_uid != portage_uid and \
925 - mystat.st_gid != portage_gid:
926 - continue
927 - myuid = -1
928 - mygid = -1
929 - if mystat.st_uid == portage_uid:
930 - myuid = inst_uid
931 - if mystat.st_gid == portage_gid:
932 - mygid = inst_gid
933 - apply_secpass_permissions(
934 - _unicode_encode(fpath, encoding=_encodings['merge']),
935 - uid=myuid, gid=mygid,
936 - mode=mystat.st_mode, stat_cached=mystat,
937 - follow_links=False)
938 -
939 - if unicode_error:
940 - break
941 -
942 - if not unicode_error:
943 - break
944 -
945 - if unicode_errors:
946 - from portage.elog.messages import eerror
947 - for l in _merge_unicode_error(unicode_errors):
948 - eerror(l, phase='install', key=mysettings.mycpv, out=out)
949 -
950 - build_info_dir = os.path.join(mysettings['PORTAGE_BUILDDIR'],
951 - 'build-info')
952 -
953 - codecs.open(_unicode_encode(os.path.join(build_info_dir,
954 - 'SIZE'), encoding=_encodings['fs'], errors='strict'),
955 - 'w', encoding=_encodings['repo.content'],
956 - errors='strict').write(str(size) + '\n')
957 -
958 - codecs.open(_unicode_encode(os.path.join(build_info_dir,
959 - 'BUILD_TIME'), encoding=_encodings['fs'], errors='strict'),
960 - 'w', encoding=_encodings['repo.content'],
961 - errors='strict').write(str(int(time.time())) + '\n')
962 -
963 - use = frozenset(mysettings['PORTAGE_USE'].split())
964 - for k in _vdb_use_conditional_keys:
965 - v = mysettings.configdict['pkg'].get(k)
966 - if v is None:
967 - continue
968 - v = dep.paren_reduce(v)
969 - v = dep.use_reduce(v, uselist=use)
970 - v = dep.paren_normalize(v)
971 - v = dep.paren_enclose(v)
972 - if not v:
973 - continue
974 - if v in _vdb_use_conditional_atoms:
975 - v_split = []
976 - for x in v.split():
977 - try:
978 - x = dep.Atom(x)
979 - except exception.InvalidAtom:
980 - v_split.append(x)
981 - else:
982 - v_split.append(str(x.evaluate_conditionals(use)))
983 - v = ' '.join(v_split)
984 - codecs.open(_unicode_encode(os.path.join(build_info_dir,
985 - k), encoding=_encodings['fs'], errors='strict'),
986 - mode='w', encoding=_encodings['repo.content'],
987 - errors='strict').write(v + '\n')
988 -
989 - if bsd_chflags:
990 - # Restore all of the flags saved above.
991 - os.system("mtree -e -p %s -U -k flags < %s > /dev/null" % \
992 - (_shell_quote(mysettings["D"]),
993 - _shell_quote(os.path.join(mysettings["T"], "bsdflags.mtree"))))
994 -
995 -def _merge_unicode_error(errors):
996 - from textwrap import wrap
997 - lines = []
998 -
999 - msg = _("This package installs one or more file names containing "
1000 - "characters that do not match your current locale "
1001 - "settings. The current setting for filesystem encoding is '%s'.") \
1002 - % _encodings['merge']
1003 - lines.extend(wrap(msg, 72))
1004 -
1005 - lines.append("")
1006 - errors.sort()
1007 - lines.extend("\t" + x for x in errors)
1008 - lines.append("")
1009 -
1010 - if _encodings['merge'].lower().replace('_', '').replace('-', '') != 'utf8':
1011 - msg = _("For best results, UTF-8 encoding is recommended. See "
1012 - "the Gentoo Linux Localization Guide for instructions "
1013 - "about how to configure your locale for UTF-8 encoding:")
1014 - lines.extend(wrap(msg, 72))
1015 - lines.append("")
1016 - lines.append("\t" + \
1017 - "http://www.gentoo.org/doc/en/guide-localization.xml")
1018 - lines.append("")
1019 -
1020 - return lines
1021 -
1022 -def _post_pkg_preinst_cmd(mysettings):
1023 - """
1024 - Post phase logic and tasks that have been factored out of
1025 - ebuild.sh. Call preinst_mask last so that INSTALL_MASK can
1026 - can be used to wipe out any gmon.out files created during
1027 - previous functions (in case any tools were built with -pg
1028 - in CFLAGS).
1029 - """
1030 -
1031 - portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
1032 - misc_sh_binary = os.path.join(portage_bin_path,
1033 - os.path.basename(MISC_SH_BINARY))
1034 -
1035 - mysettings["EBUILD_PHASE"] = ""
1036 - global _post_phase_cmds
1037 - myargs = [_shell_quote(misc_sh_binary)] + _post_phase_cmds["preinst"]
1038 -
1039 - return myargs
1040 -
1041 -def _post_pkg_postinst_cmd(mysettings):
1042 - """
1043 - Post phase logic and tasks that have been factored out of
1044 - build.sh.
1045 - """
1046 -
1047 - portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
1048 - misc_sh_binary = os.path.join(portage_bin_path,
1049 - os.path.basename(MISC_SH_BINARY))
1050 -
1051 - mysettings["EBUILD_PHASE"] = ""
1052 - global _post_phase_cmds
1053 - myargs = [_shell_quote(misc_sh_binary)] + _post_phase_cmds["postinst"]
1054 -
1055 - return myargs
1056 -
1057 -def _spawn_misc_sh(mysettings, commands, phase=None, **kwargs):
1058 - """
1059 - @param mysettings: the ebuild config
1060 - @type mysettings: config
1061 - @param commands: a list of function names to call in misc-functions.sh
1062 - @type commands: list
1063 - @rtype: int
1064 - @returns: the return value from the spawn() call
1065 - """
1066 -
1067 - # Note: PORTAGE_BIN_PATH may differ from the global
1068 - # constant when portage is reinstalling itself.
1069 - portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
1070 - misc_sh_binary = os.path.join(portage_bin_path,
1071 - os.path.basename(MISC_SH_BINARY))
1072 - mycommand = " ".join([_shell_quote(misc_sh_binary)] + commands)
1073 - _doebuild_exit_status_unlink(
1074 - mysettings.get("EBUILD_EXIT_STATUS_FILE"))
1075 - debug = mysettings.get("PORTAGE_DEBUG") == "1"
1076 - logfile = mysettings.get("PORTAGE_LOG_FILE")
1077 - mysettings.pop("EBUILD_PHASE", None)
1078 - try:
1079 - rval = spawn(mycommand, mysettings, debug=debug,
1080 - logfile=logfile, **kwargs)
1081 - finally:
1082 - pass
1083 -
1084 - msg = _doebuild_exit_status_check(phase, mysettings)
1085 - if msg:
1086 - if rval == os.EX_OK:
1087 - rval = 1
1088 - from textwrap import wrap
1089 - from portage.elog.messages import eerror
1090 - for l in wrap(msg, 72):
1091 - eerror(l, phase=mydo, key=mysettings.mycpv)
1092 -
1093 - return rval
1094 -
1095 _testing_eapis = frozenset()
1096 _deprecated_eapis = frozenset(["3_pre2", "3_pre1", "2_pre3", "2_pre2", "2_pre1"])
1097
1098 @@ -2276,1331 +1408,6 @@
1099 return (None, None)
1100 return (m.group(1), m.group(3))
1101
1102 -def doebuild_environment(myebuild, mydo, myroot, mysettings, debug, use_cache, mydbapi):
1103 -
1104 - ebuild_path = os.path.abspath(myebuild)
1105 - pkg_dir = os.path.dirname(ebuild_path)
1106 -
1107 - if "CATEGORY" in mysettings.configdict["pkg"]:
1108 - cat = mysettings.configdict["pkg"]["CATEGORY"]
1109 - else:
1110 - cat = os.path.basename(normalize_path(os.path.join(pkg_dir, "..")))
1111 -
1112 - eapi = None
1113 - if 'parse-eapi-glep-55' in mysettings.features:
1114 - mypv, eapi = portage._split_ebuild_name_glep55(
1115 - os.path.basename(myebuild))
1116 - else:
1117 - mypv = os.path.basename(ebuild_path)[:-7]
1118 -
1119 - mycpv = cat+"/"+mypv
1120 - mysplit = versions._pkgsplit(mypv)
1121 - if mysplit is None:
1122 - raise portage.exception.IncorrectParameter(
1123 - _("Invalid ebuild path: '%s'") % myebuild)
1124 -
1125 - # Make a backup of PORTAGE_TMPDIR prior to calling config.reset()
1126 - # so that the caller can override it.
1127 - tmpdir = mysettings["PORTAGE_TMPDIR"]
1128 -
1129 - if mydo == 'depend':
1130 - if mycpv != mysettings.mycpv:
1131 - # Don't pass in mydbapi here since the resulting aux_get
1132 - # call would lead to infinite 'depend' phase recursion.
1133 - mysettings.setcpv(mycpv)
1134 - else:
1135 - # If IUSE isn't in configdict['pkg'], it means that setcpv()
1136 - # hasn't been called with the mydb argument, so we have to
1137 - # call it here (portage code always calls setcpv properly,
1138 - # but api consumers might not).
1139 - if mycpv != mysettings.mycpv or \
1140 - 'IUSE' not in mysettings.configdict['pkg']:
1141 - # Reload env.d variables and reset any previous settings.
1142 - mysettings.reload()
1143 - mysettings.reset()
1144 - mysettings.setcpv(mycpv, mydb=mydbapi)
1145 -
1146 - # config.reset() might have reverted a change made by the caller,
1147 - # so restore it to it's original value.
1148 - mysettings["PORTAGE_TMPDIR"] = tmpdir
1149 -
1150 - mysettings.pop("EBUILD_PHASE", None) # remove from backupenv
1151 - mysettings["EBUILD_PHASE"] = mydo
1152 -
1153 - mysettings["PORTAGE_MASTER_PID"] = str(os.getpid())
1154 -
1155 - # We are disabling user-specific bashrc files.
1156 - mysettings["BASH_ENV"] = INVALID_ENV_FILE
1157 -
1158 - if debug: # Otherwise it overrides emerge's settings.
1159 - # We have no other way to set debug... debug can't be passed in
1160 - # due to how it's coded... Don't overwrite this so we can use it.
1161 - mysettings["PORTAGE_DEBUG"] = "1"
1162 -
1163 - mysettings["EBUILD"] = ebuild_path
1164 - mysettings["O"] = pkg_dir
1165 - mysettings.configdict["pkg"]["CATEGORY"] = cat
1166 - mysettings["FILESDIR"] = pkg_dir+"/files"
1167 - mysettings["PF"] = mypv
1168 -
1169 - if hasattr(mydbapi, '_repo_info'):
1170 - mytree = os.path.dirname(os.path.dirname(pkg_dir))
1171 - repo_info = mydbapi._repo_info[mytree]
1172 - mysettings['PORTDIR'] = repo_info.portdir
1173 - mysettings['PORTDIR_OVERLAY'] = repo_info.portdir_overlay
1174 -
1175 - mysettings["PORTDIR"] = os.path.realpath(mysettings["PORTDIR"])
1176 - mysettings["DISTDIR"] = os.path.realpath(mysettings["DISTDIR"])
1177 - mysettings["RPMDIR"] = os.path.realpath(mysettings["RPMDIR"])
1178 -
1179 - mysettings["ECLASSDIR"] = mysettings["PORTDIR"]+"/eclass"
1180 - mysettings["SANDBOX_LOG"] = mycpv.replace("/", "_-_")
1181 -
1182 - mysettings["PROFILE_PATHS"] = "\n".join(mysettings.profiles)
1183 - mysettings["P"] = mysplit[0]+"-"+mysplit[1]
1184 - mysettings["PN"] = mysplit[0]
1185 - mysettings["PV"] = mysplit[1]
1186 - mysettings["PR"] = mysplit[2]
1187 -
1188 - if portage.util.noiselimit < 0:
1189 - mysettings["PORTAGE_QUIET"] = "1"
1190 -
1191 - if mydo == 'depend' and \
1192 - 'EAPI' not in mysettings.configdict['pkg']:
1193 -
1194 - if eapi is not None:
1195 - # From parse-eapi-glep-55 above.
1196 - pass
1197 - elif 'parse-eapi-ebuild-head' in mysettings.features:
1198 - eapi = _parse_eapi_ebuild_head(
1199 - codecs.open(_unicode_encode(ebuild_path,
1200 - encoding=_encodings['fs'], errors='strict'),
1201 - mode='r', encoding=_encodings['content'], errors='replace'))
1202 -
1203 - if eapi is not None:
1204 - if not eapi_is_supported(eapi):
1205 - raise portage.exception.UnsupportedAPIException(mycpv, eapi)
1206 - mysettings.configdict['pkg']['EAPI'] = eapi
1207 -
1208 - if mydo != "depend":
1209 - # Metadata vars such as EAPI and RESTRICT are
1210 - # set by the above config.setcpv() call.
1211 - eapi = mysettings["EAPI"]
1212 - if not eapi_is_supported(eapi):
1213 - # can't do anything with this.
1214 - raise portage.exception.UnsupportedAPIException(mycpv, eapi)
1215 -
1216 - if mysplit[2] == "r0":
1217 - mysettings["PVR"]=mysplit[1]
1218 - else:
1219 - mysettings["PVR"]=mysplit[1]+"-"+mysplit[2]
1220 -
1221 - if "PATH" in mysettings:
1222 - mysplit=mysettings["PATH"].split(":")
1223 - else:
1224 - mysplit=[]
1225 - # Note: PORTAGE_BIN_PATH may differ from the global constant
1226 - # when portage is reinstalling itself.
1227 - portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
1228 - if portage_bin_path not in mysplit:
1229 - mysettings["PATH"] = portage_bin_path + ":" + mysettings["PATH"]
1230 -
1231 - # Sandbox needs cannonical paths.
1232 - mysettings["PORTAGE_TMPDIR"] = os.path.realpath(
1233 - mysettings["PORTAGE_TMPDIR"])
1234 - mysettings["BUILD_PREFIX"] = mysettings["PORTAGE_TMPDIR"]+"/portage"
1235 - mysettings["PKG_TMPDIR"] = mysettings["PORTAGE_TMPDIR"]+"/binpkgs"
1236 -
1237 - # Package {pre,post}inst and {pre,post}rm may overlap, so they must have separate
1238 - # locations in order to prevent interference.
1239 - if mydo in ("unmerge", "prerm", "postrm", "cleanrm"):
1240 - mysettings["PORTAGE_BUILDDIR"] = os.path.join(
1241 - mysettings["PKG_TMPDIR"],
1242 - mysettings["CATEGORY"], mysettings["PF"])
1243 - else:
1244 - mysettings["PORTAGE_BUILDDIR"] = os.path.join(
1245 - mysettings["BUILD_PREFIX"],
1246 - mysettings["CATEGORY"], mysettings["PF"])
1247 -
1248 - mysettings["HOME"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "homedir")
1249 - mysettings["WORKDIR"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "work")
1250 - mysettings["D"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "image") + os.sep
1251 - mysettings["T"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "temp")
1252 -
1253 - # Prefix forward compatability
1254 - mysettings["ED"] = mysettings["D"]
1255 -
1256 - mysettings["PORTAGE_BASHRC"] = os.path.join(
1257 - mysettings["PORTAGE_CONFIGROOT"], EBUILD_SH_ENV_FILE)
1258 - mysettings["EBUILD_EXIT_STATUS_FILE"] = os.path.join(
1259 - mysettings["PORTAGE_BUILDDIR"], ".exit_status")
1260 -
1261 - #set up KV variable -- DEP SPEEDUP :: Don't waste time. Keep var persistent.
1262 - if eapi not in ('0', '1', '2', '3', '3_pre2'):
1263 - # Discard KV for EAPIs that don't support it. Cache KV is restored
1264 - # from the backupenv whenever config.reset() is called.
1265 - mysettings.pop('KV', None)
1266 - elif mydo != 'depend' and 'KV' not in mysettings and \
1267 - mydo in ('compile', 'config', 'configure', 'info',
1268 - 'install', 'nofetch', 'postinst', 'postrm', 'preinst',
1269 - 'prepare', 'prerm', 'setup', 'test', 'unpack'):
1270 - mykv,err1=ExtractKernelVersion(os.path.join(myroot, "usr/src/linux"))
1271 - if mykv:
1272 - # Regular source tree
1273 - mysettings["KV"]=mykv
1274 - else:
1275 - mysettings["KV"]=""
1276 - mysettings.backup_changes("KV")
1277 -
1278 - # Allow color.map to control colors associated with einfo, ewarn, etc...
1279 - mycolors = []
1280 - for c in ("GOOD", "WARN", "BAD", "HILITE", "BRACKET"):
1281 - mycolors.append("%s=$'%s'" % \
1282 - (c, portage.output.style_to_ansi_code(c)))
1283 - mysettings["PORTAGE_COLORMAP"] = "\n".join(mycolors)
1284 -
1285 -def prepare_build_dirs(myroot, mysettings, cleanup):
1286 -
1287 - clean_dirs = [mysettings["HOME"]]
1288 -
1289 - # We enable cleanup when we want to make sure old cruft (such as the old
1290 - # environment) doesn't interfere with the current phase.
1291 - if cleanup:
1292 - clean_dirs.append(mysettings["T"])
1293 -
1294 - for clean_dir in clean_dirs:
1295 - try:
1296 - shutil.rmtree(clean_dir)
1297 - except OSError as oe:
1298 - if errno.ENOENT == oe.errno:
1299 - pass
1300 - elif errno.EPERM == oe.errno:
1301 - writemsg("%s\n" % oe, noiselevel=-1)
1302 - writemsg(_("Operation Not Permitted: rmtree('%s')\n") % \
1303 - clean_dir, noiselevel=-1)
1304 - return 1
1305 - else:
1306 - raise
1307 -
1308 - def makedirs(dir_path):
1309 - try:
1310 - os.makedirs(dir_path)
1311 - except OSError as oe:
1312 - if errno.EEXIST == oe.errno:
1313 - pass
1314 - elif errno.EPERM == oe.errno:
1315 - writemsg("%s\n" % oe, noiselevel=-1)
1316 - writemsg(_("Operation Not Permitted: makedirs('%s')\n") % \
1317 - dir_path, noiselevel=-1)
1318 - return False
1319 - else:
1320 - raise
1321 - return True
1322 -
1323 - mysettings["PKG_LOGDIR"] = os.path.join(mysettings["T"], "logging")
1324 -
1325 - mydirs = [os.path.dirname(mysettings["PORTAGE_BUILDDIR"])]
1326 - mydirs.append(os.path.dirname(mydirs[-1]))
1327 -
1328 - try:
1329 - for mydir in mydirs:
1330 - portage.util.ensure_dirs(mydir)
1331 - portage.util.apply_secpass_permissions(mydir,
1332 - gid=portage_gid, uid=portage_uid, mode=0o70, mask=0)
1333 - for dir_key in ("PORTAGE_BUILDDIR", "HOME", "PKG_LOGDIR", "T"):
1334 - """These directories don't necessarily need to be group writable.
1335 - However, the setup phase is commonly run as a privileged user prior
1336 - to the other phases being run by an unprivileged user. Currently,
1337 - we use the portage group to ensure that the unprivleged user still
1338 - has write access to these directories in any case."""
1339 - portage.util.ensure_dirs(mysettings[dir_key], mode=0o775)
1340 - portage.util.apply_secpass_permissions(mysettings[dir_key],
1341 - uid=portage_uid, gid=portage_gid)
1342 - except portage.exception.PermissionDenied as e:
1343 - writemsg(_("Permission Denied: %s\n") % str(e), noiselevel=-1)
1344 - return 1
1345 - except portage.exception.OperationNotPermitted as e:
1346 - writemsg(_("Operation Not Permitted: %s\n") % str(e), noiselevel=-1)
1347 - return 1
1348 - except portage.exception.FileNotFound as e:
1349 - writemsg(_("File Not Found: '%s'\n") % str(e), noiselevel=-1)
1350 - return 1
1351 -
1352 - # Reset state for things like noauto and keepwork in FEATURES.
1353 - for x in ('.die_hooks',):
1354 - try:
1355 - os.unlink(os.path.join(mysettings['PORTAGE_BUILDDIR'], x))
1356 - except OSError:
1357 - pass
1358 -
1359 - _prepare_workdir(mysettings)
1360 - if mysettings.get('EBUILD_PHASE') != 'fetch':
1361 - # Avoid spurious permissions adjustments when fetching with
1362 - # a temporary PORTAGE_TMPDIR setting (for fetchonly).
1363 - _prepare_features_dirs(mysettings)
1364 -
1365 -def _adjust_perms_msg(settings, msg):
1366 -
1367 - def write(msg):
1368 - writemsg(msg, noiselevel=-1)
1369 -
1370 - background = settings.get("PORTAGE_BACKGROUND") == "1"
1371 - log_path = settings.get("PORTAGE_LOG_FILE")
1372 - log_file = None
1373 -
1374 - if background and log_path is not None:
1375 - try:
1376 - log_file = codecs.open(_unicode_encode(log_path,
1377 - encoding=_encodings['fs'], errors='strict'),
1378 - mode='a', encoding=_encodings['content'], errors='replace')
1379 - except IOError:
1380 - def write(msg):
1381 - pass
1382 - else:
1383 - def write(msg):
1384 - log_file.write(_unicode_decode(msg))
1385 - log_file.flush()
1386 -
1387 - try:
1388 - write(msg)
1389 - finally:
1390 - if log_file is not None:
1391 - log_file.close()
1392 -
1393 -def _prepare_features_dirs(mysettings):
1394 -
1395 - features_dirs = {
1396 - "ccache":{
1397 - "path_dir": "/usr/lib/ccache/bin",
1398 - "basedir_var":"CCACHE_DIR",
1399 - "default_dir":os.path.join(mysettings["PORTAGE_TMPDIR"], "ccache"),
1400 - "always_recurse":False},
1401 - "distcc":{
1402 - "path_dir": "/usr/lib/distcc/bin",
1403 - "basedir_var":"DISTCC_DIR",
1404 - "default_dir":os.path.join(mysettings["BUILD_PREFIX"], ".distcc"),
1405 - "subdirs":("lock", "state"),
1406 - "always_recurse":True}
1407 - }
1408 - dirmode = 0o2070
1409 - filemode = 0o60
1410 - modemask = 0o2
1411 - restrict = mysettings.get("PORTAGE_RESTRICT","").split()
1412 - from portage.data import secpass
1413 - droppriv = secpass >= 2 and \
1414 - "userpriv" in mysettings.features and \
1415 - "userpriv" not in restrict
1416 - for myfeature, kwargs in features_dirs.items():
1417 - if myfeature in mysettings.features:
1418 - failure = False
1419 - basedir = mysettings.get(kwargs["basedir_var"])
1420 - if basedir is None or not basedir.strip():
1421 - basedir = kwargs["default_dir"]
1422 - mysettings[kwargs["basedir_var"]] = basedir
1423 - try:
1424 - path_dir = kwargs["path_dir"]
1425 - if not os.path.isdir(path_dir):
1426 - raise portage.exception.DirectoryNotFound(path_dir)
1427 -
1428 - mydirs = [mysettings[kwargs["basedir_var"]]]
1429 - if "subdirs" in kwargs:
1430 - for subdir in kwargs["subdirs"]:
1431 - mydirs.append(os.path.join(basedir, subdir))
1432 - for mydir in mydirs:
1433 - modified = portage.util.ensure_dirs(mydir)
1434 - # Generally, we only want to apply permissions for
1435 - # initial creation. Otherwise, we don't know exactly what
1436 - # permissions the user wants, so should leave them as-is.
1437 - droppriv_fix = False
1438 - if droppriv:
1439 - st = os.stat(mydir)
1440 - if st.st_gid != portage_gid or \
1441 - not dirmode == (stat.S_IMODE(st.st_mode) & dirmode):
1442 - droppriv_fix = True
1443 - if not droppriv_fix:
1444 - # Check permissions of files in the directory.
1445 - for filename in os.listdir(mydir):
1446 - try:
1447 - subdir_st = os.lstat(
1448 - os.path.join(mydir, filename))
1449 - except OSError:
1450 - continue
1451 - if subdir_st.st_gid != portage_gid or \
1452 - ((stat.S_ISDIR(subdir_st.st_mode) and \
1453 - not dirmode == (stat.S_IMODE(subdir_st.st_mode) & dirmode))):
1454 - droppriv_fix = True
1455 - break
1456 -
1457 - if droppriv_fix:
1458 - _adjust_perms_msg(mysettings,
1459 - colorize("WARN", " * ") + \
1460 - _("Adjusting permissions "
1461 - "for FEATURES=userpriv: '%s'\n") % mydir)
1462 - elif modified:
1463 - _adjust_perms_msg(mysettings,
1464 - colorize("WARN", " * ") + \
1465 - _("Adjusting permissions "
1466 - "for FEATURES=%s: '%s'\n") % (myfeature, mydir))
1467 -
1468 - if modified or kwargs["always_recurse"] or droppriv_fix:
1469 - def onerror(e):
1470 - raise # The feature is disabled if a single error
1471 - # occurs during permissions adjustment.
1472 - if not apply_recursive_permissions(mydir,
1473 - gid=portage_gid, dirmode=dirmode, dirmask=modemask,
1474 - filemode=filemode, filemask=modemask, onerror=onerror):
1475 - raise portage.exception.OperationNotPermitted(
1476 - _("Failed to apply recursive permissions for the portage group."))
1477 -
1478 - except portage.exception.DirectoryNotFound as e:
1479 - failure = True
1480 - writemsg(_("\n!!! Directory does not exist: '%s'\n") % \
1481 - (e,), noiselevel=-1)
1482 - writemsg(_("!!! Disabled FEATURES='%s'\n") % myfeature,
1483 - noiselevel=-1)
1484 -
1485 - except portage.exception.PortageException as e:
1486 - failure = True
1487 - writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
1488 - writemsg(_("!!! Failed resetting perms on %s='%s'\n") % \
1489 - (kwargs["basedir_var"], basedir), noiselevel=-1)
1490 - writemsg(_("!!! Disabled FEATURES='%s'\n") % myfeature,
1491 - noiselevel=-1)
1492 -
1493 - if failure:
1494 - mysettings.features.remove(myfeature)
1495 - mysettings['FEATURES'] = ' '.join(sorted(mysettings.features))
1496 - time.sleep(5)
1497 -
1498 -def _prepare_workdir(mysettings):
1499 - workdir_mode = 0o700
1500 - try:
1501 - mode = mysettings["PORTAGE_WORKDIR_MODE"]
1502 - if mode.isdigit():
1503 - parsed_mode = int(mode, 8)
1504 - elif mode == "":
1505 - raise KeyError()
1506 - else:
1507 - raise ValueError()
1508 - if parsed_mode & 0o7777 != parsed_mode:
1509 - raise ValueError("Invalid file mode: %s" % mode)
1510 - else:
1511 - workdir_mode = parsed_mode
1512 - except KeyError as e:
1513 - writemsg(_("!!! PORTAGE_WORKDIR_MODE is unset, using %s.\n") % oct(workdir_mode))
1514 - except ValueError as e:
1515 - if len(str(e)) > 0:
1516 - writemsg("%s\n" % e)
1517 - writemsg(_("!!! Unable to parse PORTAGE_WORKDIR_MODE='%s', using %s.\n") % \
1518 - (mysettings["PORTAGE_WORKDIR_MODE"], oct(workdir_mode)))
1519 - mysettings["PORTAGE_WORKDIR_MODE"] = oct(workdir_mode).replace('o', '')
1520 - try:
1521 - apply_secpass_permissions(mysettings["WORKDIR"],
1522 - uid=portage_uid, gid=portage_gid, mode=workdir_mode)
1523 - except portage.exception.FileNotFound:
1524 - pass # ebuild.sh will create it
1525 -
1526 - if mysettings.get("PORT_LOGDIR", "") == "":
1527 - while "PORT_LOGDIR" in mysettings:
1528 - del mysettings["PORT_LOGDIR"]
1529 - if "PORT_LOGDIR" in mysettings:
1530 - try:
1531 - modified = portage.util.ensure_dirs(mysettings["PORT_LOGDIR"])
1532 - if modified:
1533 - apply_secpass_permissions(mysettings["PORT_LOGDIR"],
1534 - uid=portage_uid, gid=portage_gid, mode=0o2770)
1535 - except portage.exception.PortageException as e:
1536 - writemsg("!!! %s\n" % str(e), noiselevel=-1)
1537 - writemsg(_("!!! Permission issues with PORT_LOGDIR='%s'\n") % \
1538 - mysettings["PORT_LOGDIR"], noiselevel=-1)
1539 - writemsg(_("!!! Disabling logging.\n"), noiselevel=-1)
1540 - while "PORT_LOGDIR" in mysettings:
1541 - del mysettings["PORT_LOGDIR"]
1542 - if "PORT_LOGDIR" in mysettings and \
1543 - os.access(mysettings["PORT_LOGDIR"], os.W_OK):
1544 - logid_path = os.path.join(mysettings["PORTAGE_BUILDDIR"], ".logid")
1545 - if not os.path.exists(logid_path):
1546 - open(_unicode_encode(logid_path), 'w')
1547 - logid_time = _unicode_decode(time.strftime("%Y%m%d-%H%M%S",
1548 - time.gmtime(os.stat(logid_path).st_mtime)),
1549 - encoding=_encodings['content'], errors='replace')
1550 -
1551 - if "split-log" in mysettings.features:
1552 - mysettings["PORTAGE_LOG_FILE"] = os.path.join(
1553 - mysettings["PORT_LOGDIR"], "build", "%s/%s:%s.log" % \
1554 - (mysettings["CATEGORY"], mysettings["PF"], logid_time))
1555 - else:
1556 - mysettings["PORTAGE_LOG_FILE"] = os.path.join(
1557 - mysettings["PORT_LOGDIR"], "%s:%s:%s.log" % \
1558 - (mysettings["CATEGORY"], mysettings["PF"], logid_time))
1559 -
1560 - util.ensure_dirs(os.path.dirname(mysettings["PORTAGE_LOG_FILE"]))
1561 -
1562 - else:
1563 - # NOTE: When sesandbox is enabled, the local SELinux security policies
1564 - # may not allow output to be piped out of the sesandbox domain. The
1565 - # current policy will allow it to work when a pty is available, but
1566 - # not through a normal pipe. See bug #162404.
1567 - mysettings["PORTAGE_LOG_FILE"] = os.path.join(
1568 - mysettings["T"], "build.log")
1569 -
1570 -def _doebuild_exit_status_check(mydo, settings):
1571 - """
1572 - Returns an error string if the shell appeared
1573 - to exit unsuccessfully, None otherwise.
1574 - """
1575 - exit_status_file = settings.get("EBUILD_EXIT_STATUS_FILE")
1576 - if not exit_status_file or \
1577 - os.path.exists(exit_status_file):
1578 - return None
1579 - msg = _("The ebuild phase '%s' has exited "
1580 - "unexpectedly. This type of behavior "
1581 - "is known to be triggered "
1582 - "by things such as failed variable "
1583 - "assignments (bug #190128) or bad substitution "
1584 - "errors (bug #200313). Normally, before exiting, bash should "
1585 - "have displayed an error message above. If bash did not "
1586 - "produce an error message above, it's possible "
1587 - "that the ebuild has called `exit` when it "
1588 - "should have called `die` instead. This behavior may also "
1589 - "be triggered by a corrupt bash binary or a hardware "
1590 - "problem such as memory or cpu malfunction. If the problem is not "
1591 - "reproducible or it appears to occur randomly, then it is likely "
1592 - "to be triggered by a hardware problem. "
1593 - "If you suspect a hardware problem then you should "
1594 - "try some basic hardware diagnostics such as memtest. "
1595 - "Please do not report this as a bug unless it is consistently "
1596 - "reproducible and you are sure that your bash binary and hardware "
1597 - "are functioning properly.") % mydo
1598 - return msg
1599 -
1600 -def _doebuild_exit_status_check_and_log(settings, mydo, retval):
1601 - msg = _doebuild_exit_status_check(mydo, settings)
1602 - if msg:
1603 - if retval == os.EX_OK:
1604 - retval = 1
1605 - from textwrap import wrap
1606 - from portage.elog.messages import eerror
1607 - for l in wrap(msg, 72):
1608 - eerror(l, phase=mydo, key=settings.mycpv)
1609 - return retval
1610 -
1611 -def _doebuild_exit_status_unlink(exit_status_file):
1612 - """
1613 - Double check to make sure it really doesn't exist
1614 - and raise an OSError if it still does (it shouldn't).
1615 - OSError if necessary.
1616 - """
1617 - if not exit_status_file:
1618 - return
1619 - try:
1620 - os.unlink(exit_status_file)
1621 - except OSError:
1622 - pass
1623 - if os.path.exists(exit_status_file):
1624 - os.unlink(exit_status_file)
1625 -
1626 -_doebuild_manifest_exempt_depend = 0
1627 -_doebuild_manifest_cache = None
1628 -_doebuild_broken_ebuilds = set()
1629 -_doebuild_broken_manifests = set()
1630 -
1631 -def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
1632 - fetchonly=0, cleanup=0, dbkey=None, use_cache=1, fetchall=0, tree=None,
1633 - mydbapi=None, vartree=None, prev_mtimes=None,
1634 - fd_pipes=None, returnpid=False):
1635 -
1636 - """
1637 - Wrapper function that invokes specific ebuild phases through the spawning
1638 - of ebuild.sh
1639 -
1640 - @param myebuild: name of the ebuild to invoke the phase on (CPV)
1641 - @type myebuild: String
1642 - @param mydo: Phase to run
1643 - @type mydo: String
1644 - @param myroot: $ROOT (usually '/', see man make.conf)
1645 - @type myroot: String
1646 - @param mysettings: Portage Configuration
1647 - @type mysettings: instance of portage.config
1648 - @param debug: Turns on various debug information (eg, debug for spawn)
1649 - @type debug: Boolean
1650 - @param listonly: Used to wrap fetch(); passed such that fetch only lists files required.
1651 - @type listonly: Boolean
1652 - @param fetchonly: Used to wrap fetch(); passed such that files are only fetched (no other actions)
1653 - @type fetchonly: Boolean
1654 - @param cleanup: Passed to prepare_build_dirs (TODO: what does it do?)
1655 - @type cleanup: Boolean
1656 - @param dbkey: A dict (usually keys and values from the depend phase, such as KEYWORDS, USE, etc..)
1657 - @type dbkey: Dict or String
1658 - @param use_cache: Enables the cache
1659 - @type use_cache: Boolean
1660 - @param fetchall: Used to wrap fetch(), fetches all URIs (even ones invalid due to USE conditionals)
1661 - @type fetchall: Boolean
1662 - @param tree: Which tree to use ('vartree','porttree','bintree', etc..), defaults to 'porttree'
1663 - @type tree: String
1664 - @param mydbapi: a dbapi instance to pass to various functions; this should be a portdbapi instance.
1665 - @type mydbapi: portdbapi instance
1666 - @param vartree: A instance of vartree; used for aux_get calls, defaults to db[myroot]['vartree']
1667 - @type vartree: vartree instance
1668 - @param prev_mtimes: A dict of { filename:mtime } keys used by merge() to do config_protection
1669 - @type prev_mtimes: dictionary
1670 - @param fd_pipes: A dict of mapping for pipes, { '0': stdin, '1': stdout }
1671 - for example.
1672 - @type fd_pipes: Dictionary
1673 - @param returnpid: Return a list of process IDs for a successful spawn, or
1674 - an integer value if spawn is unsuccessful. NOTE: This requires the
1675 - caller clean up all returned PIDs.
1676 - @type returnpid: Boolean
1677 - @rtype: Boolean
1678 - @returns:
1679 - 1. 0 for success
1680 - 2. 1 for error
1681 -
1682 - Most errors have an accompanying error message.
1683 -
1684 - listonly and fetchonly are only really necessary for operations involving 'fetch'
1685 - prev_mtimes are only necessary for merge operations.
1686 - Other variables may not be strictly required, many have defaults that are set inside of doebuild.
1687 -
1688 - """
1689 -
1690 - if not tree:
1691 - writemsg("Warning: tree not specified to doebuild\n")
1692 - tree = "porttree"
1693 - global db
1694 -
1695 - # chunked out deps for each phase, so that ebuild binary can use it
1696 - # to collapse targets down.
1697 - actionmap_deps={
1698 - "setup": [],
1699 - "unpack": ["setup"],
1700 - "prepare": ["unpack"],
1701 - "configure": ["prepare"],
1702 - "compile":["configure"],
1703 - "test": ["compile"],
1704 - "install":["test"],
1705 - "rpm": ["install"],
1706 - "package":["install"],
1707 - }
1708 -
1709 - if mydbapi is None:
1710 - mydbapi = db[myroot][tree].dbapi
1711 -
1712 - if vartree is None and mydo in ("merge", "qmerge", "unmerge"):
1713 - vartree = db[myroot]["vartree"]
1714 -
1715 - features = mysettings.features
1716 - noauto = "noauto" in features
1717 - from portage.data import secpass
1718 -
1719 - clean_phases = ("clean", "cleanrm")
1720 - validcommands = ["help","clean","prerm","postrm","cleanrm","preinst","postinst",
1721 - "config", "info", "setup", "depend", "pretend",
1722 - "fetch", "fetchall", "digest",
1723 - "unpack", "prepare", "configure", "compile", "test",
1724 - "install", "rpm", "qmerge", "merge",
1725 - "package","unmerge", "manifest"]
1726 -
1727 - if mydo not in validcommands:
1728 - validcommands.sort()
1729 - writemsg("!!! doebuild: '%s' is not one of the following valid commands:" % mydo,
1730 - noiselevel=-1)
1731 - for vcount in range(len(validcommands)):
1732 - if vcount%6 == 0:
1733 - writemsg("\n!!! ", noiselevel=-1)
1734 - writemsg(validcommands[vcount].ljust(11), noiselevel=-1)
1735 - writemsg("\n", noiselevel=-1)
1736 - return 1
1737 -
1738 - if mydo == "fetchall":
1739 - fetchall = 1
1740 - mydo = "fetch"
1741 -
1742 - parallel_fetchonly = mydo in ("fetch", "fetchall") and \
1743 - "PORTAGE_PARALLEL_FETCHONLY" in mysettings
1744 -
1745 - if mydo not in clean_phases and not os.path.exists(myebuild):
1746 - writemsg("!!! doebuild: %s not found for %s\n" % (myebuild, mydo),
1747 - noiselevel=-1)
1748 - return 1
1749 -
1750 - global _doebuild_manifest_exempt_depend
1751 -
1752 - if "strict" in features and \
1753 - "digest" not in features and \
1754 - tree == "porttree" and \
1755 - mydo not in ("digest", "manifest", "help") and \
1756 - not _doebuild_manifest_exempt_depend:
1757 - # Always verify the ebuild checksums before executing it.
1758 - global _doebuild_manifest_cache, _doebuild_broken_ebuilds, \
1759 - _doebuild_broken_ebuilds
1760 -
1761 - if myebuild in _doebuild_broken_ebuilds:
1762 - return 1
1763 -
1764 - pkgdir = os.path.dirname(myebuild)
1765 - manifest_path = os.path.join(pkgdir, "Manifest")
1766 -
1767 - # Avoid checking the same Manifest several times in a row during a
1768 - # regen with an empty cache.
1769 - if _doebuild_manifest_cache is None or \
1770 - _doebuild_manifest_cache.getFullname() != manifest_path:
1771 - _doebuild_manifest_cache = None
1772 - if not os.path.exists(manifest_path):
1773 - out = portage.output.EOutput()
1774 - out.eerror(_("Manifest not found for '%s'") % (myebuild,))
1775 - _doebuild_broken_ebuilds.add(myebuild)
1776 - return 1
1777 - mf = Manifest(pkgdir, mysettings["DISTDIR"])
1778 -
1779 - else:
1780 - mf = _doebuild_manifest_cache
1781 -
1782 - try:
1783 - mf.checkFileHashes("EBUILD", os.path.basename(myebuild))
1784 - except KeyError:
1785 - out = portage.output.EOutput()
1786 - out.eerror(_("Missing digest for '%s'") % (myebuild,))
1787 - _doebuild_broken_ebuilds.add(myebuild)
1788 - return 1
1789 - except portage.exception.FileNotFound:
1790 - out = portage.output.EOutput()
1791 - out.eerror(_("A file listed in the Manifest "
1792 - "could not be found: '%s'") % (myebuild,))
1793 - _doebuild_broken_ebuilds.add(myebuild)
1794 - return 1
1795 - except portage.exception.DigestException as e:
1796 - out = portage.output.EOutput()
1797 - out.eerror(_("Digest verification failed:"))
1798 - out.eerror("%s" % e.value[0])
1799 - out.eerror(_("Reason: %s") % e.value[1])
1800 - out.eerror(_("Got: %s") % e.value[2])
1801 - out.eerror(_("Expected: %s") % e.value[3])
1802 - _doebuild_broken_ebuilds.add(myebuild)
1803 - return 1
1804 -
1805 - if mf.getFullname() in _doebuild_broken_manifests:
1806 - return 1
1807 -
1808 - if mf is not _doebuild_manifest_cache:
1809 -
1810 - # Make sure that all of the ebuilds are
1811 - # actually listed in the Manifest.
1812 - glep55 = 'parse-eapi-glep-55' in mysettings.features
1813 - for f in os.listdir(pkgdir):
1814 - pf = None
1815 - if glep55:
1816 - pf, eapi = _split_ebuild_name_glep55(f)
1817 - elif f[-7:] == '.ebuild':
1818 - pf = f[:-7]
1819 - if pf is not None and not mf.hasFile("EBUILD", f):
1820 - f = os.path.join(pkgdir, f)
1821 - if f not in _doebuild_broken_ebuilds:
1822 - out = portage.output.EOutput()
1823 - out.eerror(_("A file is not listed in the "
1824 - "Manifest: '%s'") % (f,))
1825 - _doebuild_broken_manifests.add(manifest_path)
1826 - return 1
1827 -
1828 - # Only cache it if the above stray files test succeeds.
1829 - _doebuild_manifest_cache = mf
1830 -
1831 - def exit_status_check(retval):
1832 - msg = _doebuild_exit_status_check(mydo, mysettings)
1833 - if msg:
1834 - if retval == os.EX_OK:
1835 - retval = 1
1836 - from textwrap import wrap
1837 - from portage.elog.messages import eerror
1838 - for l in wrap(msg, 72):
1839 - eerror(l, phase=mydo, key=mysettings.mycpv)
1840 - return retval
1841 -
1842 - # Note: PORTAGE_BIN_PATH may differ from the global
1843 - # constant when portage is reinstalling itself.
1844 - portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
1845 - ebuild_sh_binary = os.path.join(portage_bin_path,
1846 - os.path.basename(EBUILD_SH_BINARY))
1847 - misc_sh_binary = os.path.join(portage_bin_path,
1848 - os.path.basename(MISC_SH_BINARY))
1849 -
1850 - logfile=None
1851 - builddir_lock = None
1852 - tmpdir = None
1853 - tmpdir_orig = None
1854 -
1855 - try:
1856 - if mydo in ("digest", "manifest", "help"):
1857 - # Temporarily exempt the depend phase from manifest checks, in case
1858 - # aux_get calls trigger cache generation.
1859 - _doebuild_manifest_exempt_depend += 1
1860 -
1861 - # If we don't need much space and we don't need a constant location,
1862 - # we can temporarily override PORTAGE_TMPDIR with a random temp dir
1863 - # so that there's no need for locking and it can be used even if the
1864 - # user isn't in the portage group.
1865 - if mydo in ("info",):
1866 - from tempfile import mkdtemp
1867 - tmpdir = mkdtemp()
1868 - tmpdir_orig = mysettings["PORTAGE_TMPDIR"]
1869 - mysettings["PORTAGE_TMPDIR"] = tmpdir
1870 -
1871 - doebuild_environment(myebuild, mydo, myroot, mysettings, debug,
1872 - use_cache, mydbapi)
1873 -
1874 - if mydo in clean_phases:
1875 - retval = spawn(_shell_quote(ebuild_sh_binary) + " clean",
1876 - mysettings, debug=debug, fd_pipes=fd_pipes, free=1,
1877 - logfile=None, returnpid=returnpid)
1878 - return retval
1879 -
1880 - restrict = set(mysettings.get('PORTAGE_RESTRICT', '').split())
1881 - # get possible slot information from the deps file
1882 - if mydo == "depend":
1883 - writemsg("!!! DEBUG: dbkey: %s\n" % str(dbkey), 2)
1884 - droppriv = "userpriv" in mysettings.features
1885 - if returnpid:
1886 - mypids = spawn(_shell_quote(ebuild_sh_binary) + " depend",
1887 - mysettings, fd_pipes=fd_pipes, returnpid=True,
1888 - droppriv=droppriv)
1889 - return mypids
1890 - elif isinstance(dbkey, dict):
1891 - mysettings["dbkey"] = ""
1892 - pr, pw = os.pipe()
1893 - fd_pipes = {
1894 - 0:sys.stdin.fileno(),
1895 - 1:sys.stdout.fileno(),
1896 - 2:sys.stderr.fileno(),
1897 - 9:pw}
1898 - mypids = spawn(_shell_quote(ebuild_sh_binary) + " depend",
1899 - mysettings,
1900 - fd_pipes=fd_pipes, returnpid=True, droppriv=droppriv)
1901 - os.close(pw) # belongs exclusively to the child process now
1902 - f = os.fdopen(pr, 'rb')
1903 - for k, v in zip(auxdbkeys,
1904 - (_unicode_decode(line).rstrip('\n') for line in f)):
1905 - dbkey[k] = v
1906 - f.close()
1907 - retval = os.waitpid(mypids[0], 0)[1]
1908 - portage.process.spawned_pids.remove(mypids[0])
1909 - # If it got a signal, return the signal that was sent, but
1910 - # shift in order to distinguish it from a return value. (just
1911 - # like portage.process.spawn() would do).
1912 - if retval & 0xff:
1913 - retval = (retval & 0xff) << 8
1914 - else:
1915 - # Otherwise, return its exit code.
1916 - retval = retval >> 8
1917 - if retval == os.EX_OK and len(dbkey) != len(auxdbkeys):
1918 - # Don't trust bash's returncode if the
1919 - # number of lines is incorrect.
1920 - retval = 1
1921 - return retval
1922 - elif dbkey:
1923 - mysettings["dbkey"] = dbkey
1924 - else:
1925 - mysettings["dbkey"] = \
1926 - os.path.join(mysettings.depcachedir, "aux_db_key_temp")
1927 -
1928 - return spawn(_shell_quote(ebuild_sh_binary) + " depend",
1929 - mysettings,
1930 - droppriv=droppriv)
1931 -
1932 - # Validate dependency metadata here to ensure that ebuilds with invalid
1933 - # data are never installed via the ebuild command. Don't bother when
1934 - # returnpid == True since there's no need to do this every time emerge
1935 - # executes a phase.
1936 - if not returnpid:
1937 - rval = _validate_deps(mysettings, myroot, mydo, mydbapi)
1938 - if rval != os.EX_OK:
1939 - return rval
1940 -
1941 - if "PORTAGE_TMPDIR" not in mysettings or \
1942 - not os.path.isdir(mysettings["PORTAGE_TMPDIR"]):
1943 - writemsg(_("The directory specified in your "
1944 - "PORTAGE_TMPDIR variable, '%s',\n"
1945 - "does not exist. Please create this directory or "
1946 - "correct your PORTAGE_TMPDIR setting.\n") % mysettings.get("PORTAGE_TMPDIR", ""), noiselevel=-1)
1947 - return 1
1948 -
1949 - # as some people use a separate PORTAGE_TMPDIR mount
1950 - # we prefer that as the checks below would otherwise be pointless
1951 - # for those people.
1952 - if os.path.exists(os.path.join(mysettings["PORTAGE_TMPDIR"], "portage")):
1953 - checkdir = os.path.join(mysettings["PORTAGE_TMPDIR"], "portage")
1954 - else:
1955 - checkdir = mysettings["PORTAGE_TMPDIR"]
1956 -
1957 - if not os.access(checkdir, os.W_OK):
1958 - writemsg(_("%s is not writable.\n"
1959 - "Likely cause is that you've mounted it as readonly.\n") % checkdir,
1960 - noiselevel=-1)
1961 - return 1
1962 - else:
1963 - from tempfile import NamedTemporaryFile
1964 - fd = NamedTemporaryFile(prefix="exectest-", dir=checkdir)
1965 - os.chmod(fd.name, 0o755)
1966 - if not os.access(fd.name, os.X_OK):
1967 - writemsg(_("Can not execute files in %s\n"
1968 - "Likely cause is that you've mounted it with one of the\n"
1969 - "following mount options: 'noexec', 'user', 'users'\n\n"
1970 - "Please make sure that portage can execute files in this directory.\n") % checkdir,
1971 - noiselevel=-1)
1972 - fd.close()
1973 - return 1
1974 - fd.close()
1975 - del checkdir
1976 -
1977 - if mydo == "unmerge":
1978 - return unmerge(mysettings["CATEGORY"],
1979 - mysettings["PF"], myroot, mysettings, vartree=vartree)
1980 -
1981 - # Build directory creation isn't required for any of these.
1982 - # In the fetch phase, the directory is needed only for RESTRICT=fetch
1983 - # in order to satisfy the sane $PWD requirement (from bug #239560)
1984 - # when pkg_nofetch is spawned.
1985 - have_build_dirs = False
1986 - if not parallel_fetchonly and \
1987 - mydo not in ('digest', 'help', 'manifest') and \
1988 - not (mydo == 'fetch' and 'fetch' not in restrict):
1989 - mystatus = prepare_build_dirs(myroot, mysettings, cleanup)
1990 - if mystatus:
1991 - return mystatus
1992 - have_build_dirs = True
1993 -
1994 - # emerge handles logging externally
1995 - if not returnpid:
1996 - # PORTAGE_LOG_FILE is set by the
1997 - # above prepare_build_dirs() call.
1998 - logfile = mysettings.get("PORTAGE_LOG_FILE")
1999 -
2000 - if have_build_dirs:
2001 - env_file = os.path.join(mysettings["T"], "environment")
2002 - env_stat = None
2003 - saved_env = None
2004 - try:
2005 - env_stat = os.stat(env_file)
2006 - except OSError as e:
2007 - if e.errno != errno.ENOENT:
2008 - raise
2009 - del e
2010 - if not env_stat:
2011 - saved_env = os.path.join(
2012 - os.path.dirname(myebuild), "environment.bz2")
2013 - if not os.path.isfile(saved_env):
2014 - saved_env = None
2015 - if saved_env:
2016 - retval = os.system(
2017 - "bzip2 -dc %s > %s" % \
2018 - (_shell_quote(saved_env),
2019 - _shell_quote(env_file)))
2020 - try:
2021 - env_stat = os.stat(env_file)
2022 - except OSError as e:
2023 - if e.errno != errno.ENOENT:
2024 - raise
2025 - del e
2026 - if os.WIFEXITED(retval) and \
2027 - os.WEXITSTATUS(retval) == os.EX_OK and \
2028 - env_stat and env_stat.st_size > 0:
2029 - # This is a signal to ebuild.sh, so that it knows to filter
2030 - # out things like SANDBOX_{DENY,PREDICT,READ,WRITE} that
2031 - # would be preserved between normal phases.
2032 - open(_unicode_encode(env_file + '.raw'), 'w')
2033 - else:
2034 - writemsg(_("!!! Error extracting saved "
2035 - "environment: '%s'\n") % \
2036 - saved_env, noiselevel=-1)
2037 - try:
2038 - os.unlink(env_file)
2039 - except OSError as e:
2040 - if e.errno != errno.ENOENT:
2041 - raise
2042 - del e
2043 - env_stat = None
2044 - if env_stat:
2045 - pass
2046 - else:
2047 - for var in ("ARCH", ):
2048 - value = mysettings.get(var)
2049 - if value and value.strip():
2050 - continue
2051 - msg = _("%(var)s is not set... "
2052 - "Are you missing the '%(configroot)setc/make.profile' symlink? "
2053 - "Is the symlink correct? "
2054 - "Is your portage tree complete?") % \
2055 - {"var": var, "configroot": mysettings["PORTAGE_CONFIGROOT"]}
2056 - from portage.elog.messages import eerror
2057 - from textwrap import wrap
2058 - for line in wrap(msg, 70):
2059 - eerror(line, phase="setup", key=mysettings.mycpv)
2060 - from portage.elog import elog_process
2061 - elog_process(mysettings.mycpv, mysettings)
2062 - return 1
2063 - del env_file, env_stat, saved_env
2064 - _doebuild_exit_status_unlink(
2065 - mysettings.get("EBUILD_EXIT_STATUS_FILE"))
2066 - else:
2067 - mysettings.pop("EBUILD_EXIT_STATUS_FILE", None)
2068 -
2069 - # if any of these are being called, handle them -- running them out of
2070 - # the sandbox -- and stop now.
2071 - if mydo == "help":
2072 - return spawn(_shell_quote(ebuild_sh_binary) + " " + mydo,
2073 - mysettings, debug=debug, free=1, logfile=logfile)
2074 - elif mydo == "setup":
2075 - retval = spawn(
2076 - _shell_quote(ebuild_sh_binary) + " " + mydo, mysettings,
2077 - debug=debug, free=1, logfile=logfile, fd_pipes=fd_pipes,
2078 - returnpid=returnpid)
2079 - if returnpid:
2080 - return retval
2081 - retval = exit_status_check(retval)
2082 - if secpass >= 2:
2083 - """ Privileged phases may have left files that need to be made
2084 - writable to a less privileged user."""
2085 - apply_recursive_permissions(mysettings["T"],
2086 - uid=portage_uid, gid=portage_gid, dirmode=0o70, dirmask=0,
2087 - filemode=0o60, filemask=0)
2088 - return retval
2089 - elif mydo == "preinst":
2090 - phase_retval = spawn(
2091 - _shell_quote(ebuild_sh_binary) + " " + mydo,
2092 - mysettings, debug=debug, free=1, logfile=logfile,
2093 - fd_pipes=fd_pipes, returnpid=returnpid)
2094 -
2095 - if returnpid:
2096 - return phase_retval
2097 -
2098 - phase_retval = exit_status_check(phase_retval)
2099 - if phase_retval == os.EX_OK:
2100 - _doebuild_exit_status_unlink(
2101 - mysettings.get("EBUILD_EXIT_STATUS_FILE"))
2102 - mysettings.pop("EBUILD_PHASE", None)
2103 - phase_retval = spawn(
2104 - " ".join(_post_pkg_preinst_cmd(mysettings)),
2105 - mysettings, debug=debug, free=1, logfile=logfile)
2106 - phase_retval = exit_status_check(phase_retval)
2107 - if phase_retval != os.EX_OK:
2108 - writemsg(_("!!! post preinst failed; exiting.\n"),
2109 - noiselevel=-1)
2110 - return phase_retval
2111 - elif mydo == "postinst":
2112 - phase_retval = spawn(
2113 - _shell_quote(ebuild_sh_binary) + " " + mydo,
2114 - mysettings, debug=debug, free=1, logfile=logfile,
2115 - fd_pipes=fd_pipes, returnpid=returnpid)
2116 -
2117 - if returnpid:
2118 - return phase_retval
2119 -
2120 - phase_retval = exit_status_check(phase_retval)
2121 - if phase_retval == os.EX_OK:
2122 - _doebuild_exit_status_unlink(
2123 - mysettings.get("EBUILD_EXIT_STATUS_FILE"))
2124 - mysettings.pop("EBUILD_PHASE", None)
2125 - phase_retval = spawn(" ".join(_post_pkg_postinst_cmd(mysettings)),
2126 - mysettings, debug=debug, free=1, logfile=logfile)
2127 - phase_retval = exit_status_check(phase_retval)
2128 - if phase_retval != os.EX_OK:
2129 - writemsg(_("!!! post postinst failed; exiting.\n"),
2130 - noiselevel=-1)
2131 - return phase_retval
2132 - elif mydo in ("prerm", "postrm", "config", "info"):
2133 - retval = spawn(
2134 - _shell_quote(ebuild_sh_binary) + " " + mydo,
2135 - mysettings, debug=debug, free=1, logfile=logfile,
2136 - fd_pipes=fd_pipes, returnpid=returnpid)
2137 -
2138 - if returnpid:
2139 - return retval
2140 -
2141 - retval = exit_status_check(retval)
2142 - return retval
2143 -
2144 - mycpv = "/".join((mysettings["CATEGORY"], mysettings["PF"]))
2145 -
2146 - emerge_skip_distfiles = returnpid
2147 - emerge_skip_digest = returnpid
2148 - # Only try and fetch the files if we are going to need them ...
2149 - # otherwise, if user has FEATURES=noauto and they run `ebuild clean
2150 - # unpack compile install`, we will try and fetch 4 times :/
2151 - need_distfiles = not emerge_skip_distfiles and \
2152 - (mydo in ("fetch", "unpack") or \
2153 - mydo not in ("digest", "manifest") and "noauto" not in features)
2154 - alist = mysettings.configdict["pkg"].get("A")
2155 - aalist = mysettings.configdict["pkg"].get("AA")
2156 - if alist is None or aalist is None:
2157 - # Make sure we get the correct tree in case there are overlays.
2158 - mytree = os.path.realpath(
2159 - os.path.dirname(os.path.dirname(mysettings["O"])))
2160 - useflags = mysettings["PORTAGE_USE"].split()
2161 - try:
2162 - alist = mydbapi.getFetchMap(mycpv, useflags=useflags,
2163 - mytree=mytree)
2164 - aalist = mydbapi.getFetchMap(mycpv, mytree=mytree)
2165 - except portage.exception.InvalidDependString as e:
2166 - writemsg("!!! %s\n" % str(e), noiselevel=-1)
2167 - writemsg(_("!!! Invalid SRC_URI for '%s'.\n") % mycpv,
2168 - noiselevel=-1)
2169 - del e
2170 - return 1
2171 - mysettings.configdict["pkg"]["A"] = " ".join(alist)
2172 - mysettings.configdict["pkg"]["AA"] = " ".join(aalist)
2173 - else:
2174 - alist = set(alist.split())
2175 - aalist = set(aalist.split())
2176 - if ("mirror" in features) or fetchall:
2177 - fetchme = aalist
2178 - checkme = aalist
2179 - else:
2180 - fetchme = alist
2181 - checkme = alist
2182 -
2183 - if mydo == "fetch":
2184 - # Files are already checked inside fetch(),
2185 - # so do not check them again.
2186 - checkme = []
2187 -
2188 - if not emerge_skip_distfiles and \
2189 - need_distfiles and not fetch(
2190 - fetchme, mysettings, listonly=listonly, fetchonly=fetchonly):
2191 - return 1
2192 -
2193 - if mydo == "fetch" and listonly:
2194 - return 0
2195 -
2196 - try:
2197 - if mydo == "manifest":
2198 - return not digestgen(mysettings=mysettings, myportdb=mydbapi)
2199 - elif mydo == "digest":
2200 - return not digestgen(mysettings=mysettings, myportdb=mydbapi)
2201 - elif mydo != 'fetch' and not emerge_skip_digest and \
2202 - "digest" in mysettings.features:
2203 - # Don't do this when called by emerge or when called just
2204 - # for fetch (especially parallel-fetch) since it's not needed
2205 - # and it can interfere with parallel tasks.
2206 - digestgen(mysettings=mysettings, myportdb=mydbapi)
2207 - except portage.exception.PermissionDenied as e:
2208 - writemsg(_("!!! Permission Denied: %s\n") % (e,), noiselevel=-1)
2209 - if mydo in ("digest", "manifest"):
2210 - return 1
2211 -
2212 - # See above comment about fetching only when needed
2213 - if not emerge_skip_distfiles and \
2214 - not digestcheck(checkme, mysettings, "strict" in features):
2215 - return 1
2216 -
2217 - if mydo == "fetch":
2218 - return 0
2219 -
2220 - # remove PORTAGE_ACTUAL_DISTDIR once cvs/svn is supported via SRC_URI
2221 - if (mydo != "setup" and "noauto" not in features) or mydo == "unpack":
2222 - orig_distdir = mysettings["DISTDIR"]
2223 - mysettings["PORTAGE_ACTUAL_DISTDIR"] = orig_distdir
2224 - edpath = mysettings["DISTDIR"] = \
2225 - os.path.join(mysettings["PORTAGE_BUILDDIR"], "distdir")
2226 - portage.util.ensure_dirs(edpath, gid=portage_gid, mode=0o755)
2227 -
2228 - # Remove any unexpected files or directories.
2229 - for x in os.listdir(edpath):
2230 - symlink_path = os.path.join(edpath, x)
2231 - st = os.lstat(symlink_path)
2232 - if x in alist and stat.S_ISLNK(st.st_mode):
2233 - continue
2234 - if stat.S_ISDIR(st.st_mode):
2235 - shutil.rmtree(symlink_path)
2236 - else:
2237 - os.unlink(symlink_path)
2238 -
2239 - # Check for existing symlinks and recreate if necessary.
2240 - for x in alist:
2241 - symlink_path = os.path.join(edpath, x)
2242 - target = os.path.join(orig_distdir, x)
2243 - try:
2244 - link_target = os.readlink(symlink_path)
2245 - except OSError:
2246 - os.symlink(target, symlink_path)
2247 - else:
2248 - if link_target != target:
2249 - os.unlink(symlink_path)
2250 - os.symlink(target, symlink_path)
2251 -
2252 - #initial dep checks complete; time to process main commands
2253 -
2254 - restrict = mysettings["PORTAGE_RESTRICT"].split()
2255 - nosandbox = (("userpriv" in features) and \
2256 - ("usersandbox" not in features) and \
2257 - "userpriv" not in restrict and \
2258 - "nouserpriv" not in restrict)
2259 - if nosandbox and ("userpriv" not in features or \
2260 - "userpriv" in restrict or \
2261 - "nouserpriv" in restrict):
2262 - nosandbox = ("sandbox" not in features and \
2263 - "usersandbox" not in features)
2264 -
2265 - if not process.sandbox_capable:
2266 - nosandbox = True
2267 -
2268 - sesandbox = mysettings.selinux_enabled() and \
2269 - "sesandbox" in mysettings.features
2270 -
2271 - droppriv = "userpriv" in mysettings.features and \
2272 - "userpriv" not in restrict and \
2273 - secpass >= 2
2274 -
2275 - fakeroot = "fakeroot" in mysettings.features
2276 -
2277 - ebuild_sh = _shell_quote(ebuild_sh_binary) + " %s"
2278 - misc_sh = _shell_quote(misc_sh_binary) + " dyn_%s"
2279 -
2280 - # args are for the to spawn function
2281 - actionmap = {
2282 -"pretend": {"cmd":ebuild_sh, "args":{"droppriv":0, "free":1, "sesandbox":0, "fakeroot":0}},
2283 -"setup": {"cmd":ebuild_sh, "args":{"droppriv":0, "free":1, "sesandbox":0, "fakeroot":0}},
2284 -"unpack": {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":0, "sesandbox":sesandbox, "fakeroot":0}},
2285 -"prepare": {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":0, "sesandbox":sesandbox, "fakeroot":0}},
2286 -"configure":{"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":nosandbox, "sesandbox":sesandbox, "fakeroot":0}},
2287 -"compile": {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":nosandbox, "sesandbox":sesandbox, "fakeroot":0}},
2288 -"test": {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":nosandbox, "sesandbox":sesandbox, "fakeroot":0}},
2289 -"install": {"cmd":ebuild_sh, "args":{"droppriv":0, "free":0, "sesandbox":sesandbox, "fakeroot":fakeroot}},
2290 -"rpm": {"cmd":misc_sh, "args":{"droppriv":0, "free":0, "sesandbox":0, "fakeroot":fakeroot}},
2291 -"package": {"cmd":misc_sh, "args":{"droppriv":0, "free":0, "sesandbox":0, "fakeroot":fakeroot}},
2292 - }
2293 -
2294 - # merge the deps in so we have again a 'full' actionmap
2295 - # be glad when this can die.
2296 - for x in actionmap:
2297 - if len(actionmap_deps.get(x, [])):
2298 - actionmap[x]["dep"] = ' '.join(actionmap_deps[x])
2299 -
2300 - if mydo in actionmap:
2301 - if mydo == "package":
2302 - # Make sure the package directory exists before executing
2303 - # this phase. This can raise PermissionDenied if
2304 - # the current user doesn't have write access to $PKGDIR.
2305 - parent_dir = os.path.join(mysettings["PKGDIR"],
2306 - mysettings["CATEGORY"])
2307 - portage.util.ensure_dirs(parent_dir)
2308 - if not os.access(parent_dir, os.W_OK):
2309 - raise portage.exception.PermissionDenied(
2310 - "access('%s', os.W_OK)" % parent_dir)
2311 - retval = spawnebuild(mydo,
2312 - actionmap, mysettings, debug, logfile=logfile,
2313 - fd_pipes=fd_pipes, returnpid=returnpid)
2314 - elif mydo=="qmerge":
2315 - # check to ensure install was run. this *only* pops up when users
2316 - # forget it and are using ebuild
2317 - if not os.path.exists(
2318 - os.path.join(mysettings["PORTAGE_BUILDDIR"], ".installed")):
2319 - writemsg(_("!!! mydo=qmerge, but the install phase has not been run\n"),
2320 - noiselevel=-1)
2321 - return 1
2322 - # qmerge is a special phase that implies noclean.
2323 - if "noclean" not in mysettings.features:
2324 - mysettings.features.add("noclean")
2325 - #qmerge is specifically not supposed to do a runtime dep check
2326 - retval = merge(
2327 - mysettings["CATEGORY"], mysettings["PF"], mysettings["D"],
2328 - os.path.join(mysettings["PORTAGE_BUILDDIR"], "build-info"),
2329 - myroot, mysettings, myebuild=mysettings["EBUILD"], mytree=tree,
2330 - mydbapi=mydbapi, vartree=vartree, prev_mtimes=prev_mtimes)
2331 - elif mydo=="merge":
2332 - retval = spawnebuild("install", actionmap, mysettings, debug,
2333 - alwaysdep=1, logfile=logfile, fd_pipes=fd_pipes,
2334 - returnpid=returnpid)
2335 - retval = exit_status_check(retval)
2336 - if retval != os.EX_OK:
2337 - # The merge phase handles this already. Callers don't know how
2338 - # far this function got, so we have to call elog_process() here
2339 - # so that it's only called once.
2340 - from portage.elog import elog_process
2341 - elog_process(mysettings.mycpv, mysettings)
2342 - if retval == os.EX_OK:
2343 - retval = merge(mysettings["CATEGORY"], mysettings["PF"],
2344 - mysettings["D"], os.path.join(mysettings["PORTAGE_BUILDDIR"],
2345 - "build-info"), myroot, mysettings,
2346 - myebuild=mysettings["EBUILD"], mytree=tree, mydbapi=mydbapi,
2347 - vartree=vartree, prev_mtimes=prev_mtimes)
2348 - else:
2349 - print(_("!!! Unknown mydo: %s") % mydo)
2350 - return 1
2351 -
2352 - return retval
2353 -
2354 - finally:
2355 -
2356 - if tmpdir:
2357 - mysettings["PORTAGE_TMPDIR"] = tmpdir_orig
2358 - shutil.rmtree(tmpdir)
2359 - if builddir_lock:
2360 - portage.locks.unlockdir(builddir_lock)
2361 -
2362 - # Make sure that DISTDIR is restored to it's normal value before we return!
2363 - if "PORTAGE_ACTUAL_DISTDIR" in mysettings:
2364 - mysettings["DISTDIR"] = mysettings["PORTAGE_ACTUAL_DISTDIR"]
2365 - del mysettings["PORTAGE_ACTUAL_DISTDIR"]
2366 -
2367 - if logfile:
2368 - try:
2369 - if os.stat(logfile).st_size == 0:
2370 - os.unlink(logfile)
2371 - except OSError:
2372 - pass
2373 -
2374 - if mydo in ("digest", "manifest", "help"):
2375 - # If necessary, depend phase has been triggered by aux_get calls
2376 - # and the exemption is no longer needed.
2377 - _doebuild_manifest_exempt_depend -= 1
2378 -
2379 -def _validate_deps(mysettings, myroot, mydo, mydbapi):
2380 -
2381 - invalid_dep_exempt_phases = \
2382 - set(["clean", "cleanrm", "help", "prerm", "postrm"])
2383 - dep_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
2384 - misc_keys = ["LICENSE", "PROPERTIES", "PROVIDE", "RESTRICT", "SRC_URI"]
2385 - other_keys = ["SLOT"]
2386 - all_keys = dep_keys + misc_keys + other_keys
2387 - metadata = dict(zip(all_keys,
2388 - mydbapi.aux_get(mysettings.mycpv, all_keys)))
2389 -
2390 - class FakeTree(object):
2391 - def __init__(self, mydb):
2392 - self.dbapi = mydb
2393 - dep_check_trees = {myroot:{}}
2394 - dep_check_trees[myroot]["porttree"] = \
2395 - FakeTree(fakedbapi(settings=mysettings))
2396 -
2397 - msgs = []
2398 - for dep_type in dep_keys:
2399 - mycheck = dep_check(metadata[dep_type], None, mysettings,
2400 - myuse="all", myroot=myroot, trees=dep_check_trees)
2401 - if not mycheck[0]:
2402 - msgs.append(" %s: %s\n %s\n" % (
2403 - dep_type, metadata[dep_type], mycheck[1]))
2404 -
2405 - for k in misc_keys:
2406 - try:
2407 - portage.dep.use_reduce(
2408 - portage.dep.paren_reduce(metadata[k]), matchall=True)
2409 - except portage.exception.InvalidDependString as e:
2410 - msgs.append(" %s: %s\n %s\n" % (
2411 - k, metadata[k], str(e)))
2412 -
2413 - if not metadata["SLOT"]:
2414 - msgs.append(_(" SLOT is undefined\n"))
2415 -
2416 - if msgs:
2417 - portage.util.writemsg_level(_("Error(s) in metadata for '%s':\n") % \
2418 - (mysettings.mycpv,), level=logging.ERROR, noiselevel=-1)
2419 - for x in msgs:
2420 - portage.util.writemsg_level(x,
2421 - level=logging.ERROR, noiselevel=-1)
2422 - if mydo not in invalid_dep_exempt_phases:
2423 - return 1
2424 -
2425 - return os.EX_OK
2426 -
2427 def _movefile(src, dest, **kwargs):
2428 """Calls movefile and raises a PortageException if an error occurs."""
2429 if movefile(src, dest, **kwargs) is None:
2430
2431 Modified: main/trunk/pym/portage/dbapi/bintree.py
2432 ===================================================================
2433 --- main/trunk/pym/portage/dbapi/bintree.py 2010-02-24 21:27:43 UTC (rev 15447)
2434 +++ main/trunk/pym/portage/dbapi/bintree.py 2010-02-25 03:37:29 UTC (rev 15448)
2435 @@ -10,6 +10,7 @@
2436 portage.proxy.lazyimport.lazyimport(globals(),
2437 'portage.dep:dep_getkey,isjustname,match_from_list',
2438 'portage.output:EOutput,colorize',
2439 + 'portage.package.ebuild.doebuild:_vdb_use_conditional_atoms',
2440 'portage.update:update_dbentries',
2441 'portage.util:ensure_dirs,normalize_path,writemsg,writemsg_stdout',
2442 'portage.versions:best,catpkgsplit,catsplit',
2443 @@ -1065,7 +1066,7 @@
2444 writemsg("%s: %s\n" % (k, str(e)),
2445 noiselevel=-1)
2446 raise
2447 - if k in portage._vdb_use_conditional_atoms:
2448 + if k in _vdb_use_conditional_atoms:
2449 v_split = []
2450 for x in deps.split():
2451 try:
2452
2453 Modified: main/trunk/pym/portage/dbapi/vartree.py
2454 ===================================================================
2455 --- main/trunk/pym/portage/dbapi/vartree.py 2010-02-24 21:27:43 UTC (rev 15447)
2456 +++ main/trunk/pym/portage/dbapi/vartree.py 2010-02-25 03:37:29 UTC (rev 15448)
2457 @@ -16,6 +16,9 @@
2458 'portage.elog:elog_process',
2459 'portage.locks:lockdir,unlockdir',
2460 'portage.output:bold,colorize',
2461 + 'portage.package.ebuild.doebuild:doebuild,doebuild_environment,' + \
2462 + '_spawn_misc_sh',
2463 + 'portage.package.ebuild.prepare_build_dirs:prepare_build_dirs',
2464 'portage.update:fixdbentries',
2465 'portage.util:apply_secpass_permissions,ConfigProtect,ensure_dirs,' + \
2466 'writemsg,writemsg_level,write_atomic,atomic_ofstream,writedict,' + \
2467 @@ -33,7 +36,7 @@
2468 from portage.localization import _
2469
2470 from portage import listdir, dep_expand, digraph, flatten, \
2471 - doebuild_environment, doebuild, env_update, prepare_build_dirs, \
2472 + env_update, \
2473 abssymlink, movefile, _movefile, bsd_chflags, cpv_getkey
2474
2475 # This is a special version of the os module, wrapped for unicode support.
2476
2477 Added: main/trunk/pym/portage/package/ebuild/_pty.py
2478 ===================================================================
2479 --- main/trunk/pym/portage/package/ebuild/_pty.py (rev 0)
2480 +++ main/trunk/pym/portage/package/ebuild/_pty.py 2010-02-25 03:37:29 UTC (rev 15448)
2481 @@ -0,0 +1,192 @@
2482 +# Copyright 2010 Gentoo Foundation
2483 +# Distributed under the terms of the GNU General Public License v2
2484 +# $Id$
2485 +
2486 +import array
2487 +import fcntl
2488 +import platform
2489 +import pty
2490 +import select
2491 +import sys
2492 +import termios
2493 +
2494 +from portage import os, _unicode_decode, _unicode_encode
2495 +from portage.process import spawn_bash
2496 +from portage.util import writemsg
2497 +
2498 +def _can_test_pty_eof():
2499 + """
2500 + The _test_pty_eof() function seems to hang on most
2501 + kernels other than Linux.
2502 + This was reported for the following kernels which used to work fine
2503 + without this EOF test: Darwin, AIX, FreeBSD. They seem to hang on
2504 + the slave_file.close() call. Note that Python's implementation of
2505 + openpty on Solaris already caused random hangs without this EOF test
2506 + and hence is globally disabled.
2507 + @rtype: bool
2508 + @returns: True if _test_pty_eof() won't hang, False otherwise.
2509 + """
2510 + return platform.system() in ("Linux",)
2511 +
2512 +def _test_pty_eof():
2513 + """
2514 + Returns True if this issues is fixed for the currently
2515 + running version of python: http://bugs.python.org/issue5380
2516 + Raises an EnvironmentError from openpty() if it fails.
2517 + """
2518 +
2519 + use_fork = False
2520 +
2521 + test_string = 2 * "blah blah blah\n"
2522 + test_string = _unicode_decode(test_string,
2523 + encoding='utf_8', errors='strict')
2524 +
2525 + # may raise EnvironmentError
2526 + master_fd, slave_fd = pty.openpty()
2527 +
2528 + # Non-blocking mode is required for Darwin kernel.
2529 + fcntl.fcntl(master_fd, fcntl.F_SETFL,
2530 + fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
2531 +
2532 + # Disable post-processing of output since otherwise weird
2533 + # things like \n -> \r\n transformations may occur.
2534 + mode = termios.tcgetattr(slave_fd)
2535 + mode[1] &= ~termios.OPOST
2536 + termios.tcsetattr(slave_fd, termios.TCSANOW, mode)
2537 +
2538 + # Simulate a subprocess writing some data to the
2539 + # slave end of the pipe, and then exiting.
2540 + pid = None
2541 + if use_fork:
2542 + pids = spawn_bash(_unicode_encode("echo -n '%s'" % test_string,
2543 + encoding='utf_8', errors='strict'), env=os.environ,
2544 + fd_pipes={0:sys.stdin.fileno(), 1:slave_fd, 2:slave_fd},
2545 + returnpid=True)
2546 + if isinstance(pids, int):
2547 + os.close(master_fd)
2548 + os.close(slave_fd)
2549 + raise EnvironmentError('spawn failed')
2550 + pid = pids[0]
2551 + else:
2552 + os.write(slave_fd, _unicode_encode(test_string,
2553 + encoding='utf_8', errors='strict'))
2554 + os.close(slave_fd)
2555 +
2556 + # If using a fork, we must wait for the child here,
2557 + # in order to avoid a race condition that would
2558 + # lead to inconsistent results.
2559 + if pid is not None:
2560 + os.waitpid(pid, 0)
2561 +
2562 + master_file = os.fdopen(master_fd, 'rb')
2563 + eof = False
2564 + data = []
2565 + iwtd = [master_file]
2566 + owtd = []
2567 + ewtd = []
2568 +
2569 + while not eof:
2570 +
2571 + events = select.select(iwtd, owtd, ewtd)
2572 + if not events[0]:
2573 + eof = True
2574 + break
2575 +
2576 + buf = array.array('B')
2577 + try:
2578 + buf.fromfile(master_file, 1024)
2579 + except EOFError:
2580 + eof = True
2581 + except IOError:
2582 + # This is where data loss occurs.
2583 + eof = True
2584 +
2585 + if not buf:
2586 + eof = True
2587 + else:
2588 + data.append(_unicode_decode(buf.tostring(),
2589 + encoding='utf_8', errors='strict'))
2590 +
2591 + master_file.close()
2592 +
2593 + return test_string == ''.join(data)
2594 +
2595 +# If _test_pty_eof() can't be used for runtime detection of
2596 +# http://bugs.python.org/issue5380, openpty can't safely be used
2597 +# unless we can guarantee that the current version of python has
2598 +# been fixed (affects all current versions of python3). When
2599 +# this issue is fixed in python3, we can add another sys.hexversion
2600 +# conditional to enable openpty support in the fixed versions.
2601 +if sys.hexversion >= 0x3000000 and not _can_test_pty_eof():
2602 + _disable_openpty = True
2603 +else:
2604 + # Disable the use of openpty on Solaris as it seems Python's openpty
2605 + # implementation doesn't play nice on Solaris with Portage's
2606 + # behaviour causing hangs/deadlocks.
2607 + # Additional note for the future: on Interix, pipes do NOT work, so
2608 + # _disable_openpty on Interix must *never* be True
2609 + _disable_openpty = platform.system() in ("SunOS",)
2610 +_tested_pty = False
2611 +
2612 +if not _can_test_pty_eof():
2613 + # Skip _test_pty_eof() on systems where it hangs.
2614 + _tested_pty = True
2615 +
2616 +def _create_pty_or_pipe(copy_term_size=None):
2617 + """
2618 + Try to create a pty and if then fails then create a normal
2619 + pipe instead.
2620 +
2621 + @param copy_term_size: If a tty file descriptor is given
2622 + then the term size will be copied to the pty.
2623 + @type copy_term_size: int
2624 + @rtype: tuple
2625 + @returns: A tuple of (is_pty, master_fd, slave_fd) where
2626 + is_pty is True if a pty was successfully allocated, and
2627 + False if a normal pipe was allocated.
2628 + """
2629 +
2630 + got_pty = False
2631 +
2632 + global _disable_openpty, _tested_pty
2633 + if not (_tested_pty or _disable_openpty):
2634 + try:
2635 + if not _test_pty_eof():
2636 + _disable_openpty = True
2637 + except EnvironmentError as e:
2638 + _disable_openpty = True
2639 + writemsg("openpty failed: '%s'\n" % str(e),
2640 + noiselevel=-1)
2641 + del e
2642 + _tested_pty = True
2643 +
2644 + if _disable_openpty:
2645 + master_fd, slave_fd = os.pipe()
2646 + else:
2647 + from pty import openpty
2648 + try:
2649 + master_fd, slave_fd = openpty()
2650 + got_pty = True
2651 + except EnvironmentError as e:
2652 + _disable_openpty = True
2653 + writemsg("openpty failed: '%s'\n" % str(e),
2654 + noiselevel=-1)
2655 + del e
2656 + master_fd, slave_fd = os.pipe()
2657 +
2658 + if got_pty:
2659 + # Disable post-processing of output since otherwise weird
2660 + # things like \n -> \r\n transformations may occur.
2661 + import termios
2662 + mode = termios.tcgetattr(slave_fd)
2663 + mode[1] &= ~termios.OPOST
2664 + termios.tcsetattr(slave_fd, termios.TCSANOW, mode)
2665 +
2666 + if got_pty and \
2667 + copy_term_size is not None and \
2668 + os.isatty(copy_term_size):
2669 + from portage.output import get_term_size, set_term_size
2670 + rows, columns = get_term_size()
2671 + set_term_size(rows, columns, slave_fd)
2672 +
2673 + return (got_pty, master_fd, slave_fd)
2674
2675
2676 Property changes on: main/trunk/pym/portage/package/ebuild/_pty.py
2677 ___________________________________________________________________
2678 Added: svn:keywords
2679 + Id
2680
2681 Added: main/trunk/pym/portage/package/ebuild/doebuild.py
2682 ===================================================================
2683 --- main/trunk/pym/portage/package/ebuild/doebuild.py (rev 0)
2684 +++ main/trunk/pym/portage/package/ebuild/doebuild.py 2010-02-25 03:37:29 UTC (rev 15448)
2685 @@ -0,0 +1,1759 @@
2686 +# Copyright 2010 Gentoo Foundation
2687 +# Distributed under the terms of the GNU General Public License v2
2688 +# $Id$
2689 +
2690 +from __future__ import print_function
2691 +
2692 +__all__ = ['doebuild', 'doebuild_environment', 'spawn', 'spawnebuild']
2693 +
2694 +import codecs
2695 +import errno
2696 +from itertools import chain
2697 +import logging
2698 +import os as _os
2699 +import re
2700 +import shutil
2701 +import stat
2702 +import sys
2703 +from textwrap import wrap
2704 +import time
2705 +
2706 +import portage
2707 +portage.proxy.lazyimport.lazyimport(globals(),
2708 + 'portage.package.ebuild.config:check_config_instance',
2709 +)
2710 +
2711 +from portage import auxdbkeys, bsd_chflags, dep_check, digestcheck, digestgen, eapi_is_supported, ExtractKernelVersion, merge, os, selinux, StringIO, unmerge, _encodings, _parse_eapi_ebuild_head, _os_merge, _shell_quote, _split_ebuild_name_glep55, _unicode_decode, _unicode_encode
2712 +from portage.const import EBUILD_SH_ENV_FILE, EBUILD_SH_BINARY, INVALID_ENV_FILE, MISC_SH_BINARY
2713 +from portage.data import portage_gid, portage_uid, secpass, uid, userpriv_groups
2714 +from portage.dbapi.virtual import fakedbapi
2715 +from portage.dep import Atom, paren_enclose, paren_normalize, paren_reduce, use_reduce
2716 +from portage.elog import elog_process
2717 +from portage.elog.messages import eerror, eqawarn
2718 +from portage.exception import DigestException, FileNotFound, IncorrectParameter, InvalidAtom, InvalidDependString, PermissionDenied, UnsupportedAPIException
2719 +from portage.localization import _
2720 +from portage.manifest import Manifest
2721 +from portage.output import style_to_ansi_code
2722 +from portage.package.ebuild.fetch import fetch
2723 +from portage.package.ebuild.prepare_build_dirs import prepare_build_dirs
2724 +from portage.package.ebuild._pty import _create_pty_or_pipe
2725 +from portage.util import apply_recursive_permissions, apply_secpass_permissions, noiselimit, normalize_path, writemsg, writemsg_stdout, write_atomic
2726 +from portage.versions import _pkgsplit
2727 +
2728 +def doebuild_environment(myebuild, mydo, myroot, mysettings,
2729 + debug, use_cache, mydbapi):
2730 +
2731 + ebuild_path = os.path.abspath(myebuild)
2732 + pkg_dir = os.path.dirname(ebuild_path)
2733 +
2734 + if "CATEGORY" in mysettings.configdict["pkg"]:
2735 + cat = mysettings.configdict["pkg"]["CATEGORY"]
2736 + else:
2737 + cat = os.path.basename(normalize_path(os.path.join(pkg_dir, "..")))
2738 +
2739 + eapi = None
2740 + if 'parse-eapi-glep-55' in mysettings.features:
2741 + mypv, eapi = _split_ebuild_name_glep55(
2742 + os.path.basename(myebuild))
2743 + else:
2744 + mypv = os.path.basename(ebuild_path)[:-7]
2745 +
2746 + mycpv = cat+"/"+mypv
2747 + mysplit = _pkgsplit(mypv)
2748 + if mysplit is None:
2749 + raise IncorrectParameter(
2750 + _("Invalid ebuild path: '%s'") % myebuild)
2751 +
2752 + # Make a backup of PORTAGE_TMPDIR prior to calling config.reset()
2753 + # so that the caller can override it.
2754 + tmpdir = mysettings["PORTAGE_TMPDIR"]
2755 +
2756 + if mydo == 'depend':
2757 + if mycpv != mysettings.mycpv:
2758 + # Don't pass in mydbapi here since the resulting aux_get
2759 + # call would lead to infinite 'depend' phase recursion.
2760 + mysettings.setcpv(mycpv)
2761 + else:
2762 + # If IUSE isn't in configdict['pkg'], it means that setcpv()
2763 + # hasn't been called with the mydb argument, so we have to
2764 + # call it here (portage code always calls setcpv properly,
2765 + # but api consumers might not).
2766 + if mycpv != mysettings.mycpv or \
2767 + 'IUSE' not in mysettings.configdict['pkg']:
2768 + # Reload env.d variables and reset any previous settings.
2769 + mysettings.reload()
2770 + mysettings.reset()
2771 + mysettings.setcpv(mycpv, mydb=mydbapi)
2772 +
2773 + # config.reset() might have reverted a change made by the caller,
2774 + # so restore it to it's original value.
2775 + mysettings["PORTAGE_TMPDIR"] = tmpdir
2776 +
2777 + mysettings.pop("EBUILD_PHASE", None) # remove from backupenv
2778 + mysettings["EBUILD_PHASE"] = mydo
2779 +
2780 + mysettings["PORTAGE_MASTER_PID"] = str(os.getpid())
2781 +
2782 + # We are disabling user-specific bashrc files.
2783 + mysettings["BASH_ENV"] = INVALID_ENV_FILE
2784 +
2785 + if debug: # Otherwise it overrides emerge's settings.
2786 + # We have no other way to set debug... debug can't be passed in
2787 + # due to how it's coded... Don't overwrite this so we can use it.
2788 + mysettings["PORTAGE_DEBUG"] = "1"
2789 +
2790 + mysettings["EBUILD"] = ebuild_path
2791 + mysettings["O"] = pkg_dir
2792 + mysettings.configdict["pkg"]["CATEGORY"] = cat
2793 + mysettings["FILESDIR"] = pkg_dir+"/files"
2794 + mysettings["PF"] = mypv
2795 +
2796 + if hasattr(mydbapi, '_repo_info'):
2797 + mytree = os.path.dirname(os.path.dirname(pkg_dir))
2798 + repo_info = mydbapi._repo_info[mytree]
2799 + mysettings['PORTDIR'] = repo_info.portdir
2800 + mysettings['PORTDIR_OVERLAY'] = repo_info.portdir_overlay
2801 +
2802 + mysettings["PORTDIR"] = os.path.realpath(mysettings["PORTDIR"])
2803 + mysettings["DISTDIR"] = os.path.realpath(mysettings["DISTDIR"])
2804 + mysettings["RPMDIR"] = os.path.realpath(mysettings["RPMDIR"])
2805 +
2806 + mysettings["ECLASSDIR"] = mysettings["PORTDIR"]+"/eclass"
2807 + mysettings["SANDBOX_LOG"] = mycpv.replace("/", "_-_")
2808 +
2809 + mysettings["PROFILE_PATHS"] = "\n".join(mysettings.profiles)
2810 + mysettings["P"] = mysplit[0]+"-"+mysplit[1]
2811 + mysettings["PN"] = mysplit[0]
2812 + mysettings["PV"] = mysplit[1]
2813 + mysettings["PR"] = mysplit[2]
2814 +
2815 + if noiselimit < 0:
2816 + mysettings["PORTAGE_QUIET"] = "1"
2817 +
2818 + if mydo == 'depend' and \
2819 + 'EAPI' not in mysettings.configdict['pkg']:
2820 +
2821 + if eapi is not None:
2822 + # From parse-eapi-glep-55 above.
2823 + pass
2824 + elif 'parse-eapi-ebuild-head' in mysettings.features:
2825 + eapi = _parse_eapi_ebuild_head(
2826 + codecs.open(_unicode_encode(ebuild_path,
2827 + encoding=_encodings['fs'], errors='strict'),
2828 + mode='r', encoding=_encodings['content'], errors='replace'))
2829 +
2830 + if eapi is not None:
2831 + if not eapi_is_supported(eapi):
2832 + raise UnsupportedAPIException(mycpv, eapi)
2833 + mysettings.configdict['pkg']['EAPI'] = eapi
2834 +
2835 + if mydo != "depend":
2836 + # Metadata vars such as EAPI and RESTRICT are
2837 + # set by the above config.setcpv() call.
2838 + eapi = mysettings["EAPI"]
2839 + if not eapi_is_supported(eapi):
2840 + # can't do anything with this.
2841 + raise UnsupportedAPIException(mycpv, eapi)
2842 +
2843 + if mysplit[2] == "r0":
2844 + mysettings["PVR"]=mysplit[1]
2845 + else:
2846 + mysettings["PVR"]=mysplit[1]+"-"+mysplit[2]
2847 +
2848 + if "PATH" in mysettings:
2849 + mysplit=mysettings["PATH"].split(":")
2850 + else:
2851 + mysplit=[]
2852 + # Note: PORTAGE_BIN_PATH may differ from the global constant
2853 + # when portage is reinstalling itself.
2854 + portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
2855 + if portage_bin_path not in mysplit:
2856 + mysettings["PATH"] = portage_bin_path + ":" + mysettings["PATH"]
2857 +
2858 + # Sandbox needs cannonical paths.
2859 + mysettings["PORTAGE_TMPDIR"] = os.path.realpath(
2860 + mysettings["PORTAGE_TMPDIR"])
2861 + mysettings["BUILD_PREFIX"] = mysettings["PORTAGE_TMPDIR"]+"/portage"
2862 + mysettings["PKG_TMPDIR"] = mysettings["PORTAGE_TMPDIR"]+"/binpkgs"
2863 +
2864 + # Package {pre,post}inst and {pre,post}rm may overlap, so they must have separate
2865 + # locations in order to prevent interference.
2866 + if mydo in ("unmerge", "prerm", "postrm", "cleanrm"):
2867 + mysettings["PORTAGE_BUILDDIR"] = os.path.join(
2868 + mysettings["PKG_TMPDIR"],
2869 + mysettings["CATEGORY"], mysettings["PF"])
2870 + else:
2871 + mysettings["PORTAGE_BUILDDIR"] = os.path.join(
2872 + mysettings["BUILD_PREFIX"],
2873 + mysettings["CATEGORY"], mysettings["PF"])
2874 +
2875 + mysettings["HOME"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "homedir")
2876 + mysettings["WORKDIR"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "work")
2877 + mysettings["D"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "image") + os.sep
2878 + mysettings["T"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "temp")
2879 +
2880 + # Prefix forward compatability
2881 + mysettings["ED"] = mysettings["D"]
2882 +
2883 + mysettings["PORTAGE_BASHRC"] = os.path.join(
2884 + mysettings["PORTAGE_CONFIGROOT"], EBUILD_SH_ENV_FILE)
2885 + mysettings["EBUILD_EXIT_STATUS_FILE"] = os.path.join(
2886 + mysettings["PORTAGE_BUILDDIR"], ".exit_status")
2887 +
2888 + #set up KV variable -- DEP SPEEDUP :: Don't waste time. Keep var persistent.
2889 + if eapi not in ('0', '1', '2', '3', '3_pre2'):
2890 + # Discard KV for EAPIs that don't support it. Cache KV is restored
2891 + # from the backupenv whenever config.reset() is called.
2892 + mysettings.pop('KV', None)
2893 + elif mydo != 'depend' and 'KV' not in mysettings and \
2894 + mydo in ('compile', 'config', 'configure', 'info',
2895 + 'install', 'nofetch', 'postinst', 'postrm', 'preinst',
2896 + 'prepare', 'prerm', 'setup', 'test', 'unpack'):
2897 + mykv,err1=ExtractKernelVersion(os.path.join(myroot, "usr/src/linux"))
2898 + if mykv:
2899 + # Regular source tree
2900 + mysettings["KV"]=mykv
2901 + else:
2902 + mysettings["KV"]=""
2903 + mysettings.backup_changes("KV")
2904 +
2905 + # Allow color.map to control colors associated with einfo, ewarn, etc...
2906 + mycolors = []
2907 + for c in ("GOOD", "WARN", "BAD", "HILITE", "BRACKET"):
2908 + mycolors.append("%s=$'%s'" % \
2909 + (c, style_to_ansi_code(c)))
2910 + mysettings["PORTAGE_COLORMAP"] = "\n".join(mycolors)
2911 +
2912 +def _doebuild_exit_status_check(mydo, settings):
2913 + """
2914 + Returns an error string if the shell appeared
2915 + to exit unsuccessfully, None otherwise.
2916 + """
2917 + exit_status_file = settings.get("EBUILD_EXIT_STATUS_FILE")
2918 + if not exit_status_file or \
2919 + os.path.exists(exit_status_file):
2920 + return None
2921 + msg = _("The ebuild phase '%s' has exited "
2922 + "unexpectedly. This type of behavior "
2923 + "is known to be triggered "
2924 + "by things such as failed variable "
2925 + "assignments (bug #190128) or bad substitution "
2926 + "errors (bug #200313). Normally, before exiting, bash should "
2927 + "have displayed an error message above. If bash did not "
2928 + "produce an error message above, it's possible "
2929 + "that the ebuild has called `exit` when it "
2930 + "should have called `die` instead. This behavior may also "
2931 + "be triggered by a corrupt bash binary or a hardware "
2932 + "problem such as memory or cpu malfunction. If the problem is not "
2933 + "reproducible or it appears to occur randomly, then it is likely "
2934 + "to be triggered by a hardware problem. "
2935 + "If you suspect a hardware problem then you should "
2936 + "try some basic hardware diagnostics such as memtest. "
2937 + "Please do not report this as a bug unless it is consistently "
2938 + "reproducible and you are sure that your bash binary and hardware "
2939 + "are functioning properly.") % mydo
2940 + return msg
2941 +
2942 +def _doebuild_exit_status_check_and_log(settings, mydo, retval):
2943 + msg = _doebuild_exit_status_check(mydo, settings)
2944 + if msg:
2945 + if retval == os.EX_OK:
2946 + retval = 1
2947 + for l in wrap(msg, 72):
2948 + eerror(l, phase=mydo, key=settings.mycpv)
2949 + return retval
2950 +
2951 +def _doebuild_exit_status_unlink(exit_status_file):
2952 + """
2953 + Double check to make sure it really doesn't exist
2954 + and raise an OSError if it still does (it shouldn't).
2955 + OSError if necessary.
2956 + """
2957 + if not exit_status_file:
2958 + return
2959 + try:
2960 + os.unlink(exit_status_file)
2961 + except OSError:
2962 + pass
2963 + if os.path.exists(exit_status_file):
2964 + os.unlink(exit_status_file)
2965 +
2966 +_doebuild_manifest_exempt_depend = 0
2967 +_doebuild_manifest_cache = None
2968 +_doebuild_broken_ebuilds = set()
2969 +_doebuild_broken_manifests = set()
2970 +
2971 +def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
2972 + fetchonly=0, cleanup=0, dbkey=None, use_cache=1, fetchall=0, tree=None,
2973 + mydbapi=None, vartree=None, prev_mtimes=None,
2974 + fd_pipes=None, returnpid=False):
2975 +
2976 + """
2977 + Wrapper function that invokes specific ebuild phases through the spawning
2978 + of ebuild.sh
2979 +
2980 + @param myebuild: name of the ebuild to invoke the phase on (CPV)
2981 + @type myebuild: String
2982 + @param mydo: Phase to run
2983 + @type mydo: String
2984 + @param myroot: $ROOT (usually '/', see man make.conf)
2985 + @type myroot: String
2986 + @param mysettings: Portage Configuration
2987 + @type mysettings: instance of portage.config
2988 + @param debug: Turns on various debug information (eg, debug for spawn)
2989 + @type debug: Boolean
2990 + @param listonly: Used to wrap fetch(); passed such that fetch only lists files required.
2991 + @type listonly: Boolean
2992 + @param fetchonly: Used to wrap fetch(); passed such that files are only fetched (no other actions)
2993 + @type fetchonly: Boolean
2994 + @param cleanup: Passed to prepare_build_dirs (TODO: what does it do?)
2995 + @type cleanup: Boolean
2996 + @param dbkey: A dict (usually keys and values from the depend phase, such as KEYWORDS, USE, etc..)
2997 + @type dbkey: Dict or String
2998 + @param use_cache: Enables the cache
2999 + @type use_cache: Boolean
3000 + @param fetchall: Used to wrap fetch(), fetches all URIs (even ones invalid due to USE conditionals)
3001 + @type fetchall: Boolean
3002 + @param tree: Which tree to use ('vartree','porttree','bintree', etc..), defaults to 'porttree'
3003 + @type tree: String
3004 + @param mydbapi: a dbapi instance to pass to various functions; this should be a portdbapi instance.
3005 + @type mydbapi: portdbapi instance
3006 + @param vartree: A instance of vartree; used for aux_get calls, defaults to db[myroot]['vartree']
3007 + @type vartree: vartree instance
3008 + @param prev_mtimes: A dict of { filename:mtime } keys used by merge() to do config_protection
3009 + @type prev_mtimes: dictionary
3010 + @param fd_pipes: A dict of mapping for pipes, { '0': stdin, '1': stdout }
3011 + for example.
3012 + @type fd_pipes: Dictionary
3013 + @param returnpid: Return a list of process IDs for a successful spawn, or
3014 + an integer value if spawn is unsuccessful. NOTE: This requires the
3015 + caller clean up all returned PIDs.
3016 + @type returnpid: Boolean
3017 + @rtype: Boolean
3018 + @returns:
3019 + 1. 0 for success
3020 + 2. 1 for error
3021 +
3022 + Most errors have an accompanying error message.
3023 +
3024 + listonly and fetchonly are only really necessary for operations involving 'fetch'
3025 + prev_mtimes are only necessary for merge operations.
3026 + Other variables may not be strictly required, many have defaults that are set inside of doebuild.
3027 +
3028 + """
3029 +
3030 + if not tree:
3031 + writemsg("Warning: tree not specified to doebuild\n")
3032 + tree = "porttree"
3033 +
3034 + # chunked out deps for each phase, so that ebuild binary can use it
3035 + # to collapse targets down.
3036 + actionmap_deps={
3037 + "setup": [],
3038 + "unpack": ["setup"],
3039 + "prepare": ["unpack"],
3040 + "configure": ["prepare"],
3041 + "compile":["configure"],
3042 + "test": ["compile"],
3043 + "install":["test"],
3044 + "rpm": ["install"],
3045 + "package":["install"],
3046 + }
3047 +
3048 + if mydbapi is None:
3049 + mydbapi = portage.db[myroot][tree].dbapi
3050 +
3051 + if vartree is None and mydo in ("merge", "qmerge", "unmerge"):
3052 + vartree = portage.db[myroot]["vartree"]
3053 +
3054 + features = mysettings.features
3055 +
3056 + clean_phases = ("clean", "cleanrm")
3057 + validcommands = ["help","clean","prerm","postrm","cleanrm","preinst","postinst",
3058 + "config", "info", "setup", "depend", "pretend",
3059 + "fetch", "fetchall", "digest",
3060 + "unpack", "prepare", "configure", "compile", "test",
3061 + "install", "rpm", "qmerge", "merge",
3062 + "package","unmerge", "manifest"]
3063 +
3064 + if mydo not in validcommands:
3065 + validcommands.sort()
3066 + writemsg("!!! doebuild: '%s' is not one of the following valid commands:" % mydo,
3067 + noiselevel=-1)
3068 + for vcount in range(len(validcommands)):
3069 + if vcount%6 == 0:
3070 + writemsg("\n!!! ", noiselevel=-1)
3071 + writemsg(validcommands[vcount].ljust(11), noiselevel=-1)
3072 + writemsg("\n", noiselevel=-1)
3073 + return 1
3074 +
3075 + if mydo == "fetchall":
3076 + fetchall = 1
3077 + mydo = "fetch"
3078 +
3079 + parallel_fetchonly = mydo in ("fetch", "fetchall") and \
3080 + "PORTAGE_PARALLEL_FETCHONLY" in mysettings
3081 +
3082 + if mydo not in clean_phases and not os.path.exists(myebuild):
3083 + writemsg("!!! doebuild: %s not found for %s\n" % (myebuild, mydo),
3084 + noiselevel=-1)
3085 + return 1
3086 +
3087 + global _doebuild_manifest_exempt_depend
3088 +
3089 + if "strict" in features and \
3090 + "digest" not in features and \
3091 + tree == "porttree" and \
3092 + mydo not in ("digest", "manifest", "help") and \
3093 + not _doebuild_manifest_exempt_depend:
3094 + # Always verify the ebuild checksums before executing it.
3095 + global _doebuild_manifest_cache, _doebuild_broken_ebuilds, \
3096 + _doebuild_broken_ebuilds
3097 +
3098 + if myebuild in _doebuild_broken_ebuilds:
3099 + return 1
3100 +
3101 + pkgdir = os.path.dirname(myebuild)
3102 + manifest_path = os.path.join(pkgdir, "Manifest")
3103 +
3104 + # Avoid checking the same Manifest several times in a row during a
3105 + # regen with an empty cache.
3106 + if _doebuild_manifest_cache is None or \
3107 + _doebuild_manifest_cache.getFullname() != manifest_path:
3108 + _doebuild_manifest_cache = None
3109 + if not os.path.exists(manifest_path):
3110 + out = portage.output.EOutput()
3111 + out.eerror(_("Manifest not found for '%s'") % (myebuild,))
3112 + _doebuild_broken_ebuilds.add(myebuild)
3113 + return 1
3114 + mf = Manifest(pkgdir, mysettings["DISTDIR"])
3115 +
3116 + else:
3117 + mf = _doebuild_manifest_cache
3118 +
3119 + try:
3120 + mf.checkFileHashes("EBUILD", os.path.basename(myebuild))
3121 + except KeyError:
3122 + out = portage.output.EOutput()
3123 + out.eerror(_("Missing digest for '%s'") % (myebuild,))
3124 + _doebuild_broken_ebuilds.add(myebuild)
3125 + return 1
3126 + except FileNotFound:
3127 + out = portage.output.EOutput()
3128 + out.eerror(_("A file listed in the Manifest "
3129 + "could not be found: '%s'") % (myebuild,))
3130 + _doebuild_broken_ebuilds.add(myebuild)
3131 + return 1
3132 + except DigestException as e:
3133 + out = portage.output.EOutput()
3134 + out.eerror(_("Digest verification failed:"))
3135 + out.eerror("%s" % e.value[0])
3136 + out.eerror(_("Reason: %s") % e.value[1])
3137 + out.eerror(_("Got: %s") % e.value[2])
3138 + out.eerror(_("Expected: %s") % e.value[3])
3139 + _doebuild_broken_ebuilds.add(myebuild)
3140 + return 1
3141 +
3142 + if mf.getFullname() in _doebuild_broken_manifests:
3143 + return 1
3144 +
3145 + if mf is not _doebuild_manifest_cache:
3146 +
3147 + # Make sure that all of the ebuilds are
3148 + # actually listed in the Manifest.
3149 + glep55 = 'parse-eapi-glep-55' in mysettings.features
3150 + for f in os.listdir(pkgdir):
3151 + pf = None
3152 + if glep55:
3153 + pf, eapi = _split_ebuild_name_glep55(f)
3154 + elif f[-7:] == '.ebuild':
3155 + pf = f[:-7]
3156 + if pf is not None and not mf.hasFile("EBUILD", f):
3157 + f = os.path.join(pkgdir, f)
3158 + if f not in _doebuild_broken_ebuilds:
3159 + out = portage.output.EOutput()
3160 + out.eerror(_("A file is not listed in the "
3161 + "Manifest: '%s'") % (f,))
3162 + _doebuild_broken_manifests.add(manifest_path)
3163 + return 1
3164 +
3165 + # Only cache it if the above stray files test succeeds.
3166 + _doebuild_manifest_cache = mf
3167 +
3168 + def exit_status_check(retval):
3169 + msg = _doebuild_exit_status_check(mydo, mysettings)
3170 + if msg:
3171 + if retval == os.EX_OK:
3172 + retval = 1
3173 + for l in wrap(msg, 72):
3174 + eerror(l, phase=mydo, key=mysettings.mycpv)
3175 + return retval
3176 +
3177 + # Note: PORTAGE_BIN_PATH may differ from the global
3178 + # constant when portage is reinstalling itself.
3179 + portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
3180 + ebuild_sh_binary = os.path.join(portage_bin_path,
3181 + os.path.basename(EBUILD_SH_BINARY))
3182 + misc_sh_binary = os.path.join(portage_bin_path,
3183 + os.path.basename(MISC_SH_BINARY))
3184 +
3185 + logfile=None
3186 + builddir_lock = None
3187 + tmpdir = None
3188 + tmpdir_orig = None
3189 +
3190 + try:
3191 + if mydo in ("digest", "manifest", "help"):
3192 + # Temporarily exempt the depend phase from manifest checks, in case
3193 + # aux_get calls trigger cache generation.
3194 + _doebuild_manifest_exempt_depend += 1
3195 +
3196 + # If we don't need much space and we don't need a constant location,
3197 + # we can temporarily override PORTAGE_TMPDIR with a random temp dir
3198 + # so that there's no need for locking and it can be used even if the
3199 + # user isn't in the portage group.
3200 + if mydo in ("info",):
3201 + from tempfile import mkdtemp
3202 + tmpdir = mkdtemp()
3203 + tmpdir_orig = mysettings["PORTAGE_TMPDIR"]
3204 + mysettings["PORTAGE_TMPDIR"] = tmpdir
3205 +
3206 + doebuild_environment(myebuild, mydo, myroot, mysettings, debug,
3207 + use_cache, mydbapi)
3208 +
3209 + if mydo in clean_phases:
3210 + retval = spawn(_shell_quote(ebuild_sh_binary) + " clean",
3211 + mysettings, debug=debug, fd_pipes=fd_pipes, free=1,
3212 + logfile=None, returnpid=returnpid)
3213 + return retval
3214 +
3215 + restrict = set(mysettings.get('PORTAGE_RESTRICT', '').split())
3216 + # get possible slot information from the deps file
3217 + if mydo == "depend":
3218 + writemsg("!!! DEBUG: dbkey: %s\n" % str(dbkey), 2)
3219 + droppriv = "userpriv" in mysettings.features
3220 + if returnpid:
3221 + mypids = spawn(_shell_quote(ebuild_sh_binary) + " depend",
3222 + mysettings, fd_pipes=fd_pipes, returnpid=True,
3223 + droppriv=droppriv)
3224 + return mypids
3225 + elif isinstance(dbkey, dict):
3226 + mysettings["dbkey"] = ""
3227 + pr, pw = os.pipe()
3228 + fd_pipes = {
3229 + 0:sys.stdin.fileno(),
3230 + 1:sys.stdout.fileno(),
3231 + 2:sys.stderr.fileno(),
3232 + 9:pw}
3233 + mypids = spawn(_shell_quote(ebuild_sh_binary) + " depend",
3234 + mysettings,
3235 + fd_pipes=fd_pipes, returnpid=True, droppriv=droppriv)
3236 + os.close(pw) # belongs exclusively to the child process now
3237 + f = os.fdopen(pr, 'rb')
3238 + for k, v in zip(auxdbkeys,
3239 + (_unicode_decode(line).rstrip('\n') for line in f)):
3240 + dbkey[k] = v
3241 + f.close()
3242 + retval = os.waitpid(mypids[0], 0)[1]
3243 + portage.process.spawned_pids.remove(mypids[0])
3244 + # If it got a signal, return the signal that was sent, but
3245 + # shift in order to distinguish it from a return value. (just
3246 + # like portage.process.spawn() would do).
3247 + if retval & 0xff:
3248 + retval = (retval & 0xff) << 8
3249 + else:
3250 + # Otherwise, return its exit code.
3251 + retval = retval >> 8
3252 + if retval == os.EX_OK and len(dbkey) != len(auxdbkeys):
3253 + # Don't trust bash's returncode if the
3254 + # number of lines is incorrect.
3255 + retval = 1
3256 + return retval
3257 + elif dbkey:
3258 + mysettings["dbkey"] = dbkey
3259 + else:
3260 + mysettings["dbkey"] = \
3261 + os.path.join(mysettings.depcachedir, "aux_db_key_temp")
3262 +
3263 + return spawn(_shell_quote(ebuild_sh_binary) + " depend",
3264 + mysettings,
3265 + droppriv=droppriv)
3266 +
3267 + # Validate dependency metadata here to ensure that ebuilds with invalid
3268 + # data are never installed via the ebuild command. Don't bother when
3269 + # returnpid == True since there's no need to do this every time emerge
3270 + # executes a phase.
3271 + if not returnpid:
3272 + rval = _validate_deps(mysettings, myroot, mydo, mydbapi)
3273 + if rval != os.EX_OK:
3274 + return rval
3275 +
3276 + if "PORTAGE_TMPDIR" not in mysettings or \
3277 + not os.path.isdir(mysettings["PORTAGE_TMPDIR"]):
3278 + writemsg(_("The directory specified in your "
3279 + "PORTAGE_TMPDIR variable, '%s',\n"
3280 + "does not exist. Please create this directory or "
3281 + "correct your PORTAGE_TMPDIR setting.\n") % mysettings.get("PORTAGE_TMPDIR", ""), noiselevel=-1)
3282 + return 1
3283 +
3284 + # as some people use a separate PORTAGE_TMPDIR mount
3285 + # we prefer that as the checks below would otherwise be pointless
3286 + # for those people.
3287 + if os.path.exists(os.path.join(mysettings["PORTAGE_TMPDIR"], "portage")):
3288 + checkdir = os.path.join(mysettings["PORTAGE_TMPDIR"], "portage")
3289 + else:
3290 + checkdir = mysettings["PORTAGE_TMPDIR"]
3291 +
3292 + if not os.access(checkdir, os.W_OK):
3293 + writemsg(_("%s is not writable.\n"
3294 + "Likely cause is that you've mounted it as readonly.\n") % checkdir,
3295 + noiselevel=-1)
3296 + return 1
3297 + else:
3298 + from tempfile import NamedTemporaryFile
3299 + fd = NamedTemporaryFile(prefix="exectest-", dir=checkdir)
3300 + os.chmod(fd.name, 0o755)
3301 + if not os.access(fd.name, os.X_OK):
3302 + writemsg(_("Can not execute files in %s\n"
3303 + "Likely cause is that you've mounted it with one of the\n"
3304 + "following mount options: 'noexec', 'user', 'users'\n\n"
3305 + "Please make sure that portage can execute files in this directory.\n") % checkdir,
3306 + noiselevel=-1)
3307 + fd.close()
3308 + return 1
3309 + fd.close()
3310 + del checkdir
3311 +
3312 + if mydo == "unmerge":
3313 + return unmerge(mysettings["CATEGORY"],
3314 + mysettings["PF"], myroot, mysettings, vartree=vartree)
3315 +
3316 + # Build directory creation isn't required for any of these.
3317 + # In the fetch phase, the directory is needed only for RESTRICT=fetch
3318 + # in order to satisfy the sane $PWD requirement (from bug #239560)
3319 + # when pkg_nofetch is spawned.
3320 + have_build_dirs = False
3321 + if not parallel_fetchonly and \
3322 + mydo not in ('digest', 'help', 'manifest') and \
3323 + not (mydo == 'fetch' and 'fetch' not in restrict):
3324 + mystatus = prepare_build_dirs(myroot, mysettings, cleanup)
3325 + if mystatus:
3326 + return mystatus
3327 + have_build_dirs = True
3328 +
3329 + # emerge handles logging externally
3330 + if not returnpid:
3331 + # PORTAGE_LOG_FILE is set by the
3332 + # above prepare_build_dirs() call.
3333 + logfile = mysettings.get("PORTAGE_LOG_FILE")
3334 +
3335 + if have_build_dirs:
3336 + env_file = os.path.join(mysettings["T"], "environment")
3337 + env_stat = None
3338 + saved_env = None
3339 + try:
3340 + env_stat = os.stat(env_file)
3341 + except OSError as e:
3342 + if e.errno != errno.ENOENT:
3343 + raise
3344 + del e
3345 + if not env_stat:
3346 + saved_env = os.path.join(
3347 + os.path.dirname(myebuild), "environment.bz2")
3348 + if not os.path.isfile(saved_env):
3349 + saved_env = None
3350 + if saved_env:
3351 + retval = os.system(
3352 + "bzip2 -dc %s > %s" % \
3353 + (_shell_quote(saved_env),
3354 + _shell_quote(env_file)))
3355 + try:
3356 + env_stat = os.stat(env_file)
3357 + except OSError as e:
3358 + if e.errno != errno.ENOENT:
3359 + raise
3360 + del e
3361 + if os.WIFEXITED(retval) and \
3362 + os.WEXITSTATUS(retval) == os.EX_OK and \
3363 + env_stat and env_stat.st_size > 0:
3364 + # This is a signal to ebuild.sh, so that it knows to filter
3365 + # out things like SANDBOX_{DENY,PREDICT,READ,WRITE} that
3366 + # would be preserved between normal phases.
3367 + open(_unicode_encode(env_file + '.raw'), 'w')
3368 + else:
3369 + writemsg(_("!!! Error extracting saved "
3370 + "environment: '%s'\n") % \
3371 + saved_env, noiselevel=-1)
3372 + try:
3373 + os.unlink(env_file)
3374 + except OSError as e:
3375 + if e.errno != errno.ENOENT:
3376 + raise
3377 + del e
3378 + env_stat = None
3379 + if env_stat:
3380 + pass
3381 + else:
3382 + for var in ("ARCH", ):
3383 + value = mysettings.get(var)
3384 + if value and value.strip():
3385 + continue
3386 + msg = _("%(var)s is not set... "
3387 + "Are you missing the '%(configroot)setc/make.profile' symlink? "
3388 + "Is the symlink correct? "
3389 + "Is your portage tree complete?") % \
3390 + {"var": var, "configroot": mysettings["PORTAGE_CONFIGROOT"]}
3391 + for line in wrap(msg, 70):
3392 + eerror(line, phase="setup", key=mysettings.mycpv)
3393 + elog_process(mysettings.mycpv, mysettings)
3394 + return 1
3395 + del env_file, env_stat, saved_env
3396 + _doebuild_exit_status_unlink(
3397 + mysettings.get("EBUILD_EXIT_STATUS_FILE"))
3398 + else:
3399 + mysettings.pop("EBUILD_EXIT_STATUS_FILE", None)
3400 +
3401 + # if any of these are being called, handle them -- running them out of
3402 + # the sandbox -- and stop now.
3403 + if mydo == "help":
3404 + return spawn(_shell_quote(ebuild_sh_binary) + " " + mydo,
3405 + mysettings, debug=debug, free=1, logfile=logfile)
3406 + elif mydo == "setup":
3407 + retval = spawn(
3408 + _shell_quote(ebuild_sh_binary) + " " + mydo, mysettings,
3409 + debug=debug, free=1, logfile=logfile, fd_pipes=fd_pipes,
3410 + returnpid=returnpid)
3411 + if returnpid:
3412 + return retval
3413 + retval = exit_status_check(retval)
3414 + if secpass >= 2:
3415 + """ Privileged phases may have left files that need to be made
3416 + writable to a less privileged user."""
3417 + apply_recursive_permissions(mysettings["T"],
3418 + uid=portage_uid, gid=portage_gid, dirmode=0o70, dirmask=0,
3419 + filemode=0o60, filemask=0)
3420 + return retval
3421 + elif mydo == "preinst":
3422 + phase_retval = spawn(
3423 + _shell_quote(ebuild_sh_binary) + " " + mydo,
3424 + mysettings, debug=debug, free=1, logfile=logfile,
3425 + fd_pipes=fd_pipes, returnpid=returnpid)
3426 +
3427 + if returnpid:
3428 + return phase_retval
3429 +
3430 + phase_retval = exit_status_check(phase_retval)
3431 + if phase_retval == os.EX_OK:
3432 + _doebuild_exit_status_unlink(
3433 + mysettings.get("EBUILD_EXIT_STATUS_FILE"))
3434 + mysettings.pop("EBUILD_PHASE", None)
3435 + phase_retval = spawn(
3436 + " ".join(_post_pkg_preinst_cmd(mysettings)),
3437 + mysettings, debug=debug, free=1, logfile=logfile)
3438 + phase_retval = exit_status_check(phase_retval)
3439 + if phase_retval != os.EX_OK:
3440 + writemsg(_("!!! post preinst failed; exiting.\n"),
3441 + noiselevel=-1)
3442 + return phase_retval
3443 + elif mydo == "postinst":
3444 + phase_retval = spawn(
3445 + _shell_quote(ebuild_sh_binary) + " " + mydo,
3446 + mysettings, debug=debug, free=1, logfile=logfile,
3447 + fd_pipes=fd_pipes, returnpid=returnpid)
3448 +
3449 + if returnpid:
3450 + return phase_retval
3451 +
3452 + phase_retval = exit_status_check(phase_retval)
3453 + if phase_retval == os.EX_OK:
3454 + _doebuild_exit_status_unlink(
3455 + mysettings.get("EBUILD_EXIT_STATUS_FILE"))
3456 + mysettings.pop("EBUILD_PHASE", None)
3457 + phase_retval = spawn(" ".join(_post_pkg_postinst_cmd(mysettings)),
3458 + mysettings, debug=debug, free=1, logfile=logfile)
3459 + phase_retval = exit_status_check(phase_retval)
3460 + if phase_retval != os.EX_OK:
3461 + writemsg(_("!!! post postinst failed; exiting.\n"),
3462 + noiselevel=-1)
3463 + return phase_retval
3464 + elif mydo in ("prerm", "postrm", "config", "info"):
3465 + retval = spawn(
3466 + _shell_quote(ebuild_sh_binary) + " " + mydo,
3467 + mysettings, debug=debug, free=1, logfile=logfile,
3468 + fd_pipes=fd_pipes, returnpid=returnpid)
3469 +
3470 + if returnpid:
3471 + return retval
3472 +
3473 + retval = exit_status_check(retval)
3474 + return retval
3475 +
3476 + mycpv = "/".join((mysettings["CATEGORY"], mysettings["PF"]))
3477 +
3478 + emerge_skip_distfiles = returnpid
3479 + emerge_skip_digest = returnpid
3480 + # Only try and fetch the files if we are going to need them ...
3481 + # otherwise, if user has FEATURES=noauto and they run `ebuild clean
3482 + # unpack compile install`, we will try and fetch 4 times :/
3483 + need_distfiles = not emerge_skip_distfiles and \
3484 + (mydo in ("fetch", "unpack") or \
3485 + mydo not in ("digest", "manifest") and "noauto" not in features)
3486 + alist = mysettings.configdict["pkg"].get("A")
3487 + aalist = mysettings.configdict["pkg"].get("AA")
3488 + if alist is None or aalist is None:
3489 + # Make sure we get the correct tree in case there are overlays.
3490 + mytree = os.path.realpath(
3491 + os.path.dirname(os.path.dirname(mysettings["O"])))
3492 + useflags = mysettings["PORTAGE_USE"].split()
3493 + try:
3494 + alist = mydbapi.getFetchMap(mycpv, useflags=useflags,
3495 + mytree=mytree)
3496 + aalist = mydbapi.getFetchMap(mycpv, mytree=mytree)
3497 + except InvalidDependString as e:
3498 + writemsg("!!! %s\n" % str(e), noiselevel=-1)
3499 + writemsg(_("!!! Invalid SRC_URI for '%s'.\n") % mycpv,
3500 + noiselevel=-1)
3501 + del e
3502 + return 1
3503 + mysettings.configdict["pkg"]["A"] = " ".join(alist)
3504 + mysettings.configdict["pkg"]["AA"] = " ".join(aalist)
3505 + else:
3506 + alist = set(alist.split())
3507 + aalist = set(aalist.split())
3508 + if ("mirror" in features) or fetchall:
3509 + fetchme = aalist
3510 + checkme = aalist
3511 + else:
3512 + fetchme = alist
3513 + checkme = alist
3514 +
3515 + if mydo == "fetch":
3516 + # Files are already checked inside fetch(),
3517 + # so do not check them again.
3518 + checkme = []
3519 +
3520 + if not emerge_skip_distfiles and \
3521 + need_distfiles and not fetch(
3522 + fetchme, mysettings, listonly=listonly, fetchonly=fetchonly):
3523 + return 1
3524 +
3525 + if mydo == "fetch" and listonly:
3526 + return 0
3527 +
3528 + try:
3529 + if mydo == "manifest":
3530 + return not digestgen(mysettings=mysettings, myportdb=mydbapi)
3531 + elif mydo == "digest":
3532 + return not digestgen(mysettings=mysettings, myportdb=mydbapi)
3533 + elif mydo != 'fetch' and not emerge_skip_digest and \
3534 + "digest" in mysettings.features:
3535 + # Don't do this when called by emerge or when called just
3536 + # for fetch (especially parallel-fetch) since it's not needed
3537 + # and it can interfere with parallel tasks.
3538 + digestgen(mysettings=mysettings, myportdb=mydbapi)
3539 + except PermissionDenied as e:
3540 + writemsg(_("!!! Permission Denied: %s\n") % (e,), noiselevel=-1)
3541 + if mydo in ("digest", "manifest"):
3542 + return 1
3543 +
3544 + # See above comment about fetching only when needed
3545 + if not emerge_skip_distfiles and \
3546 + not digestcheck(checkme, mysettings, "strict" in features):
3547 + return 1
3548 +
3549 + if mydo == "fetch":
3550 + return 0
3551 +
3552 + # remove PORTAGE_ACTUAL_DISTDIR once cvs/svn is supported via SRC_URI
3553 + if (mydo != "setup" and "noauto" not in features) or mydo == "unpack":
3554 + orig_distdir = mysettings["DISTDIR"]
3555 + mysettings["PORTAGE_ACTUAL_DISTDIR"] = orig_distdir
3556 + edpath = mysettings["DISTDIR"] = \
3557 + os.path.join(mysettings["PORTAGE_BUILDDIR"], "distdir")
3558 + portage.util.ensure_dirs(edpath, gid=portage_gid, mode=0o755)
3559 +
3560 + # Remove any unexpected files or directories.
3561 + for x in os.listdir(edpath):
3562 + symlink_path = os.path.join(edpath, x)
3563 + st = os.lstat(symlink_path)
3564 + if x in alist and stat.S_ISLNK(st.st_mode):
3565 + continue
3566 + if stat.S_ISDIR(st.st_mode):
3567 + shutil.rmtree(symlink_path)
3568 + else:
3569 + os.unlink(symlink_path)
3570 +
3571 + # Check for existing symlinks and recreate if necessary.
3572 + for x in alist:
3573 + symlink_path = os.path.join(edpath, x)
3574 + target = os.path.join(orig_distdir, x)
3575 + try:
3576 + link_target = os.readlink(symlink_path)
3577 + except OSError:
3578 + os.symlink(target, symlink_path)
3579 + else:
3580 + if link_target != target:
3581 + os.unlink(symlink_path)
3582 + os.symlink(target, symlink_path)
3583 +
3584 + #initial dep checks complete; time to process main commands
3585 +
3586 + restrict = mysettings["PORTAGE_RESTRICT"].split()
3587 + nosandbox = (("userpriv" in features) and \
3588 + ("usersandbox" not in features) and \
3589 + "userpriv" not in restrict and \
3590 + "nouserpriv" not in restrict)
3591 + if nosandbox and ("userpriv" not in features or \
3592 + "userpriv" in restrict or \
3593 + "nouserpriv" in restrict):
3594 + nosandbox = ("sandbox" not in features and \
3595 + "usersandbox" not in features)
3596 +
3597 + if not portage.process.sandbox_capable:
3598 + nosandbox = True
3599 +
3600 + sesandbox = mysettings.selinux_enabled() and \
3601 + "sesandbox" in mysettings.features
3602 +
3603 + droppriv = "userpriv" in mysettings.features and \
3604 + "userpriv" not in restrict and \
3605 + secpass >= 2
3606 +
3607 + fakeroot = "fakeroot" in mysettings.features
3608 +
3609 + ebuild_sh = _shell_quote(ebuild_sh_binary) + " %s"
3610 + misc_sh = _shell_quote(misc_sh_binary) + " dyn_%s"
3611 +
3612 + # args are for the to spawn function
3613 + actionmap = {
3614 +"pretend": {"cmd":ebuild_sh, "args":{"droppriv":0, "free":1, "sesandbox":0, "fakeroot":0}},
3615 +"setup": {"cmd":ebuild_sh, "args":{"droppriv":0, "free":1, "sesandbox":0, "fakeroot":0}},
3616 +"unpack": {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":0, "sesandbox":sesandbox, "fakeroot":0}},
3617 +"prepare": {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":0, "sesandbox":sesandbox, "fakeroot":0}},
3618 +"configure":{"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":nosandbox, "sesandbox":sesandbox, "fakeroot":0}},
3619 +"compile": {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":nosandbox, "sesandbox":sesandbox, "fakeroot":0}},
3620 +"test": {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":nosandbox, "sesandbox":sesandbox, "fakeroot":0}},
3621 +"install": {"cmd":ebuild_sh, "args":{"droppriv":0, "free":0, "sesandbox":sesandbox, "fakeroot":fakeroot}},
3622 +"rpm": {"cmd":misc_sh, "args":{"droppriv":0, "free":0, "sesandbox":0, "fakeroot":fakeroot}},
3623 +"package": {"cmd":misc_sh, "args":{"droppriv":0, "free":0, "sesandbox":0, "fakeroot":fakeroot}},
3624 + }
3625 +
3626 + # merge the deps in so we have again a 'full' actionmap
3627 + # be glad when this can die.
3628 + for x in actionmap:
3629 + if len(actionmap_deps.get(x, [])):
3630 + actionmap[x]["dep"] = ' '.join(actionmap_deps[x])
3631 +
3632 + if mydo in actionmap:
3633 + if mydo == "package":
3634 + # Make sure the package directory exists before executing
3635 + # this phase. This can raise PermissionDenied if
3636 + # the current user doesn't have write access to $PKGDIR.
3637 + parent_dir = os.path.join(mysettings["PKGDIR"],
3638 + mysettings["CATEGORY"])
3639 + portage.util.ensure_dirs(parent_dir)
3640 + if not os.access(parent_dir, os.W_OK):
3641 + raise PermissionDenied(
3642 + "access('%s', os.W_OK)" % parent_dir)
3643 + retval = spawnebuild(mydo,
3644 + actionmap, mysettings, debug, logfile=logfile,
3645 + fd_pipes=fd_pipes, returnpid=returnpid)
3646 + elif mydo=="qmerge":
3647 + # check to ensure install was run. this *only* pops up when users
3648 + # forget it and are using ebuild
3649 + if not os.path.exists(
3650 + os.path.join(mysettings["PORTAGE_BUILDDIR"], ".installed")):
3651 + writemsg(_("!!! mydo=qmerge, but the install phase has not been run\n"),
3652 + noiselevel=-1)
3653 + return 1
3654 + # qmerge is a special phase that implies noclean.
3655 + if "noclean" not in mysettings.features:
3656 + mysettings.features.add("noclean")
3657 + #qmerge is specifically not supposed to do a runtime dep check
3658 + retval = merge(
3659 + mysettings["CATEGORY"], mysettings["PF"], mysettings["D"],
3660 + os.path.join(mysettings["PORTAGE_BUILDDIR"], "build-info"),
3661 + myroot, mysettings, myebuild=mysettings["EBUILD"], mytree=tree,
3662 + mydbapi=mydbapi, vartree=vartree, prev_mtimes=prev_mtimes)
3663 + elif mydo=="merge":
3664 + retval = spawnebuild("install", actionmap, mysettings, debug,
3665 + alwaysdep=1, logfile=logfile, fd_pipes=fd_pipes,
3666 + returnpid=returnpid)
3667 + retval = exit_status_check(retval)
3668 + if retval != os.EX_OK:
3669 + # The merge phase handles this already. Callers don't know how
3670 + # far this function got, so we have to call elog_process() here
3671 + # so that it's only called once.
3672 + from portage.elog import elog_process
3673 + elog_process(mysettings.mycpv, mysettings)
3674 + if retval == os.EX_OK:
3675 + retval = merge(mysettings["CATEGORY"], mysettings["PF"],
3676 + mysettings["D"], os.path.join(mysettings["PORTAGE_BUILDDIR"],
3677 + "build-info"), myroot, mysettings,
3678 + myebuild=mysettings["EBUILD"], mytree=tree, mydbapi=mydbapi,
3679 + vartree=vartree, prev_mtimes=prev_mtimes)
3680 + else:
3681 + print(_("!!! Unknown mydo: %s") % mydo)
3682 + return 1
3683 +
3684 + return retval
3685 +
3686 + finally:
3687 +
3688 + if tmpdir:
3689 + mysettings["PORTAGE_TMPDIR"] = tmpdir_orig
3690 + shutil.rmtree(tmpdir)
3691 + if builddir_lock:
3692 + portage.locks.unlockdir(builddir_lock)
3693 +
3694 + # Make sure that DISTDIR is restored to it's normal value before we return!
3695 + if "PORTAGE_ACTUAL_DISTDIR" in mysettings:
3696 + mysettings["DISTDIR"] = mysettings["PORTAGE_ACTUAL_DISTDIR"]
3697 + del mysettings["PORTAGE_ACTUAL_DISTDIR"]
3698 +
3699 + if logfile:
3700 + try:
3701 + if os.stat(logfile).st_size == 0:
3702 + os.unlink(logfile)
3703 + except OSError:
3704 + pass
3705 +
3706 + if mydo in ("digest", "manifest", "help"):
3707 + # If necessary, depend phase has been triggered by aux_get calls
3708 + # and the exemption is no longer needed.
3709 + _doebuild_manifest_exempt_depend -= 1
3710 +
3711 +def _validate_deps(mysettings, myroot, mydo, mydbapi):
3712 +
3713 + invalid_dep_exempt_phases = \
3714 + set(["clean", "cleanrm", "help", "prerm", "postrm"])
3715 + dep_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
3716 + misc_keys = ["LICENSE", "PROPERTIES", "PROVIDE", "RESTRICT", "SRC_URI"]
3717 + other_keys = ["SLOT"]
3718 + all_keys = dep_keys + misc_keys + other_keys
3719 + metadata = dict(zip(all_keys,
3720 + mydbapi.aux_get(mysettings.mycpv, all_keys)))
3721 +
3722 + class FakeTree(object):
3723 + def __init__(self, mydb):
3724 + self.dbapi = mydb
3725 + dep_check_trees = {myroot:{}}
3726 + dep_check_trees[myroot]["porttree"] = \
3727 + FakeTree(fakedbapi(settings=mysettings))
3728 +
3729 + msgs = []
3730 + for dep_type in dep_keys:
3731 + mycheck = dep_check(metadata[dep_type], None, mysettings,
3732 + myuse="all", myroot=myroot, trees=dep_check_trees)
3733 + if not mycheck[0]:
3734 + msgs.append(" %s: %s\n %s\n" % (
3735 + dep_type, metadata[dep_type], mycheck[1]))
3736 +
3737 + for k in misc_keys:
3738 + try:
3739 + use_reduce(
3740 + paren_reduce(metadata[k]), matchall=True)
3741 + except InvalidDependString as e:
3742 + msgs.append(" %s: %s\n %s\n" % (
3743 + k, metadata[k], str(e)))
3744 +
3745 + if not metadata["SLOT"]:
3746 + msgs.append(_(" SLOT is undefined\n"))
3747 +
3748 + if msgs:
3749 + portage.util.writemsg_level(_("Error(s) in metadata for '%s':\n") % \
3750 + (mysettings.mycpv,), level=logging.ERROR, noiselevel=-1)
3751 + for x in msgs:
3752 + portage.util.writemsg_level(x,
3753 + level=logging.ERROR, noiselevel=-1)
3754 + if mydo not in invalid_dep_exempt_phases:
3755 + return 1
3756 +
3757 + return os.EX_OK
3758 +
3759 +# XXX This would be to replace getstatusoutput completely.
3760 +# XXX Issue: cannot block execution. Deadlock condition.
3761 +def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakeroot=0, **keywords):
3762 + """
3763 + Spawn a subprocess with extra portage-specific options.
3764 + Optiosn include:
3765 +
3766 + Sandbox: Sandbox means the spawned process will be limited in its ability t
3767 + read and write files (normally this means it is restricted to ${D}/)
3768 + SElinux Sandbox: Enables sandboxing on SElinux
3769 + Reduced Privileges: Drops privilages such that the process runs as portage:portage
3770 + instead of as root.
3771 +
3772 + Notes: os.system cannot be used because it messes with signal handling. Instead we
3773 + use the portage.process spawn* family of functions.
3774 +
3775 + This function waits for the process to terminate.
3776 +
3777 + @param mystring: Command to run
3778 + @type mystring: String
3779 + @param mysettings: Either a Dict of Key,Value pairs or an instance of portage.config
3780 + @type mysettings: Dictionary or config instance
3781 + @param debug: Ignored
3782 + @type debug: Boolean
3783 + @param free: Enable sandboxing for this process
3784 + @type free: Boolean
3785 + @param droppriv: Drop to portage:portage when running this command
3786 + @type droppriv: Boolean
3787 + @param sesandbox: Enable SELinux Sandboxing (toggles a context switch)
3788 + @type sesandbox: Boolean
3789 + @param fakeroot: Run this command with faked root privileges
3790 + @type fakeroot: Boolean
3791 + @param keywords: Extra options encoded as a dict, to be passed to spawn
3792 + @type keywords: Dictionary
3793 + @rtype: Integer
3794 + @returns:
3795 + 1. The return code of the spawned process.
3796 + """
3797 +
3798 + if isinstance(mysettings, dict):
3799 + env=mysettings
3800 + keywords["opt_name"]="[ %s ]" % "portage"
3801 + else:
3802 + check_config_instance(mysettings)
3803 + env=mysettings.environ()
3804 + if mysettings.mycpv is not None:
3805 + keywords["opt_name"] = "[%s]" % mysettings.mycpv
3806 + else:
3807 + keywords["opt_name"] = "[%s/%s]" % \
3808 + (mysettings.get("CATEGORY",""), mysettings.get("PF",""))
3809 +
3810 + fd_pipes = keywords.get("fd_pipes")
3811 + if fd_pipes is None:
3812 + fd_pipes = {
3813 + 0:sys.stdin.fileno(),
3814 + 1:sys.stdout.fileno(),
3815 + 2:sys.stderr.fileno(),
3816 + }
3817 + # In some cases the above print statements don't flush stdout, so
3818 + # it needs to be flushed before allowing a child process to use it
3819 + # so that output always shows in the correct order.
3820 + stdout_filenos = (sys.stdout.fileno(), sys.stderr.fileno())
3821 + for fd in fd_pipes.values():
3822 + if fd in stdout_filenos:
3823 + sys.stdout.flush()
3824 + sys.stderr.flush()
3825 + break
3826 +
3827 + # The default policy for the sesandbox domain only allows entry (via exec)
3828 + # from shells and from binaries that belong to portage (the number of entry
3829 + # points is minimized). The "tee" binary is not among the allowed entry
3830 + # points, so it is spawned outside of the sesandbox domain and reads from a
3831 + # pseudo-terminal that connects two domains.
3832 + logfile = keywords.get("logfile")
3833 + mypids = []
3834 + master_fd = None
3835 + slave_fd = None
3836 + fd_pipes_orig = None
3837 + got_pty = False
3838 + if logfile:
3839 + del keywords["logfile"]
3840 + if 1 not in fd_pipes or 2 not in fd_pipes:
3841 + raise ValueError(fd_pipes)
3842 +
3843 + got_pty, master_fd, slave_fd = \
3844 + _create_pty_or_pipe(copy_term_size=fd_pipes[1])
3845 +
3846 + if not got_pty and 'sesandbox' in mysettings.features \
3847 + and mysettings.selinux_enabled():
3848 + # With sesandbox, logging works through a pty but not through a
3849 + # normal pipe. So, disable logging if ptys are broken.
3850 + # See Bug #162404.
3851 + logfile = None
3852 + os.close(master_fd)
3853 + master_fd = None
3854 + os.close(slave_fd)
3855 + slave_fd = None
3856 +
3857 + if logfile:
3858 +
3859 + fd_pipes.setdefault(0, sys.stdin.fileno())
3860 + fd_pipes_orig = fd_pipes.copy()
3861 +
3862 + # We must set non-blocking mode before we close the slave_fd
3863 + # since otherwise the fcntl call can fail on FreeBSD (the child
3864 + # process might have already exited and closed slave_fd so we
3865 + # have to keep it open in order to avoid FreeBSD potentially
3866 + # generating an EAGAIN exception).
3867 + import fcntl
3868 + fcntl.fcntl(master_fd, fcntl.F_SETFL,
3869 + fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
3870 +
3871 + fd_pipes[0] = fd_pipes_orig[0]
3872 + fd_pipes[1] = slave_fd
3873 + fd_pipes[2] = slave_fd
3874 + keywords["fd_pipes"] = fd_pipes
3875 +
3876 + features = mysettings.features
3877 + # TODO: Enable fakeroot to be used together with droppriv. The
3878 + # fake ownership/permissions will have to be converted to real
3879 + # permissions in the merge phase.
3880 + fakeroot = fakeroot and uid != 0 and portage.process.fakeroot_capable
3881 + if droppriv and not uid and portage_gid and portage_uid:
3882 + keywords.update({"uid":portage_uid,"gid":portage_gid,
3883 + "groups":userpriv_groups,"umask":0o02})
3884 + if not free:
3885 + free=((droppriv and "usersandbox" not in features) or \
3886 + (not droppriv and "sandbox" not in features and \
3887 + "usersandbox" not in features and not fakeroot))
3888 +
3889 + if not free and not (fakeroot or portage.process.sandbox_capable):
3890 + free = True
3891 +
3892 + if free or "SANDBOX_ACTIVE" in os.environ:
3893 + keywords["opt_name"] += " bash"
3894 + spawn_func = portage.process.spawn_bash
3895 + elif fakeroot:
3896 + keywords["opt_name"] += " fakeroot"
3897 + keywords["fakeroot_state"] = os.path.join(mysettings["T"], "fakeroot.state")
3898 + spawn_func = portage.process.spawn_fakeroot
3899 + else:
3900 + keywords["opt_name"] += " sandbox"
3901 + spawn_func = portage.process.spawn_sandbox
3902 +
3903 + if sesandbox:
3904 + spawn_func = selinux.spawn_wrapper(spawn_func,
3905 + mysettings["PORTAGE_SANDBOX_T"])
3906 +
3907 + returnpid = keywords.get("returnpid")
3908 + keywords["returnpid"] = True
3909 + try:
3910 + mypids.extend(spawn_func(mystring, env=env, **keywords))
3911 + finally:
3912 + if logfile:
3913 + os.close(slave_fd)
3914 +
3915 + if returnpid:
3916 + return mypids
3917 +
3918 + if logfile:
3919 + log_file = open(_unicode_encode(logfile), mode='ab')
3920 + apply_secpass_permissions(logfile,
3921 + uid=portage_uid, gid=portage_gid, mode=0o664)
3922 + stdout_file = os.fdopen(os.dup(fd_pipes_orig[1]), 'wb')
3923 + master_file = os.fdopen(master_fd, 'rb')
3924 + iwtd = [master_file]
3925 + owtd = []
3926 + ewtd = []
3927 + import array, select
3928 + buffsize = 65536
3929 + eof = False
3930 + while not eof:
3931 + events = select.select(iwtd, owtd, ewtd)
3932 + for f in events[0]:
3933 + # Use non-blocking mode to prevent read
3934 + # calls from blocking indefinitely.
3935 + buf = array.array('B')
3936 + try:
3937 + buf.fromfile(f, buffsize)
3938 + except EOFError:
3939 + pass
3940 + if not buf:
3941 + eof = True
3942 + break
3943 + if f is master_file:
3944 + buf.tofile(stdout_file)
3945 + stdout_file.flush()
3946 + buf.tofile(log_file)
3947 + log_file.flush()
3948 + log_file.close()
3949 + stdout_file.close()
3950 + master_file.close()
3951 + pid = mypids[-1]
3952 + retval = os.waitpid(pid, 0)[1]
3953 + portage.process.spawned_pids.remove(pid)
3954 + if retval != os.EX_OK:
3955 + if retval & 0xff:
3956 + return (retval & 0xff) << 8
3957 + return retval >> 8
3958 + return retval
3959 +
3960 +
3961 +# parse actionmap to spawn ebuild with the appropriate args
3962 +def spawnebuild(mydo, actionmap, mysettings, debug, alwaysdep=0,
3963 + logfile=None, fd_pipes=None, returnpid=False):
3964 + if not returnpid and \
3965 + (alwaysdep or "noauto" not in mysettings.features):
3966 + # process dependency first
3967 + if "dep" in actionmap[mydo]:
3968 + retval = spawnebuild(actionmap[mydo]["dep"], actionmap,
3969 + mysettings, debug, alwaysdep=alwaysdep, logfile=logfile,
3970 + fd_pipes=fd_pipes, returnpid=returnpid)
3971 + if retval:
3972 + return retval
3973 +
3974 + eapi = mysettings["EAPI"]
3975 +
3976 + if mydo == "configure" and eapi in ("0", "1"):
3977 + return os.EX_OK
3978 +
3979 + if mydo == "prepare" and eapi in ("0", "1"):
3980 + return os.EX_OK
3981 +
3982 + if mydo == "pretend" and eapi in ("0", "1", "2", "3", "3_pre2"):
3983 + return os.EX_OK
3984 +
3985 + kwargs = actionmap[mydo]["args"]
3986 + mysettings["EBUILD_PHASE"] = mydo
3987 + _doebuild_exit_status_unlink(
3988 + mysettings.get("EBUILD_EXIT_STATUS_FILE"))
3989 +
3990 + try:
3991 + phase_retval = spawn(actionmap[mydo]["cmd"] % mydo,
3992 + mysettings, debug=debug, logfile=logfile,
3993 + fd_pipes=fd_pipes, returnpid=returnpid, **kwargs)
3994 + finally:
3995 + mysettings["EBUILD_PHASE"] = ""
3996 +
3997 + if returnpid:
3998 + return phase_retval
3999 +
4000 + msg = _doebuild_exit_status_check(mydo, mysettings)
4001 + if msg:
4002 + if phase_retval == os.EX_OK:
4003 + phase_retval = 1
4004 + for l in wrap(msg, 72):
4005 + eerror(l, phase=mydo, key=mysettings.mycpv)
4006 +
4007 + _post_phase_userpriv_perms(mysettings)
4008 + if mydo == "install":
4009 + out = StringIO()
4010 + _check_build_log(mysettings, out=out)
4011 + msg = _unicode_decode(out.getvalue(),
4012 + encoding=_encodings['content'], errors='replace')
4013 + if msg:
4014 + writemsg_stdout(msg, noiselevel=-1)
4015 + if logfile is not None:
4016 + try:
4017 + f = codecs.open(_unicode_encode(logfile,
4018 + encoding=_encodings['fs'], errors='strict'),
4019 + mode='a', encoding=_encodings['content'],
4020 + errors='replace')
4021 + except EnvironmentError:
4022 + pass
4023 + else:
4024 + f.write(msg)
4025 + f.close()
4026 + if phase_retval == os.EX_OK:
4027 + _post_src_install_chost_fix(mysettings)
4028 + phase_retval = _post_src_install_checks(mysettings)
4029 +
4030 + if mydo == "test" and phase_retval != os.EX_OK and \
4031 + "test-fail-continue" in mysettings.features:
4032 + phase_retval = os.EX_OK
4033 +
4034 + return phase_retval
4035 +
4036 +_post_phase_cmds = {
4037 +
4038 + "install" : [
4039 + "install_qa_check",
4040 + "install_symlink_html_docs"],
4041 +
4042 + "preinst" : [
4043 + "preinst_bsdflags",
4044 + "preinst_sfperms",
4045 + "preinst_selinux_labels",
4046 + "preinst_suid_scan",
4047 + "preinst_mask"],
4048 +
4049 + "postinst" : [
4050 + "postinst_bsdflags"]
4051 +}
4052 +
4053 +def _post_phase_userpriv_perms(mysettings):
4054 + if "userpriv" in mysettings.features and secpass >= 2:
4055 + """ Privileged phases may have left files that need to be made
4056 + writable to a less privileged user."""
4057 + apply_recursive_permissions(mysettings["T"],
4058 + uid=portage_uid, gid=portage_gid, dirmode=0o70, dirmask=0,
4059 + filemode=0o60, filemask=0)
4060 +
4061 +def _post_src_install_checks(mysettings):
4062 + _post_src_install_uid_fix(mysettings)
4063 + global _post_phase_cmds
4064 + retval = _spawn_misc_sh(mysettings, _post_phase_cmds["install"],
4065 + phase='internal_post_src_install')
4066 + if retval != os.EX_OK:
4067 + writemsg(_("!!! install_qa_check failed; exiting.\n"),
4068 + noiselevel=-1)
4069 + return retval
4070 +
4071 +def _check_build_log(mysettings, out=None):
4072 + """
4073 + Search the content of $PORTAGE_LOG_FILE if it exists
4074 + and generate the following QA Notices when appropriate:
4075 +
4076 + * Automake "maintainer mode"
4077 + * command not found
4078 + * Unrecognized configure options
4079 + """
4080 + logfile = mysettings.get("PORTAGE_LOG_FILE")
4081 + if logfile is None:
4082 + return
4083 + try:
4084 + f = codecs.open(_unicode_encode(logfile,
4085 + encoding=_encodings['fs'], errors='strict'),
4086 + mode='r', encoding=_encodings['content'], errors='replace')
4087 + except EnvironmentError:
4088 + return
4089 +
4090 + am_maintainer_mode = []
4091 + bash_command_not_found = []
4092 + bash_command_not_found_re = re.compile(
4093 + r'(.*): line (\d*): (.*): command not found$')
4094 + command_not_found_exclude_re = re.compile(r'/configure: line ')
4095 + helper_missing_file = []
4096 + helper_missing_file_re = re.compile(
4097 + r'^!!! (do|new).*: .* does not exist$')
4098 +
4099 + configure_opts_warn = []
4100 + configure_opts_warn_re = re.compile(
4101 + r'^configure: WARNING: [Uu]nrecognized options: ')
4102 +
4103 + # Exclude output from dev-libs/yaz-3.0.47 which looks like this:
4104 + #
4105 + #Configuration:
4106 + # Automake: ${SHELL} /var/tmp/portage/dev-libs/yaz-3.0.47/work/yaz-3.0.47/config/missing --run automake-1.10
4107 + am_maintainer_mode_re = re.compile(r'/missing --run ')
4108 + am_maintainer_mode_exclude_re = \
4109 + re.compile(r'(/missing --run (autoheader|makeinfo)|^\s*Automake:\s)')
4110 +
4111 + make_jobserver_re = \
4112 + re.compile(r'g?make\[\d+\]: warning: jobserver unavailable:')
4113 + make_jobserver = []
4114 +
4115 + try:
4116 + for line in f:
4117 + if am_maintainer_mode_re.search(line) is not None and \
4118 + am_maintainer_mode_exclude_re.search(line) is None:
4119 + am_maintainer_mode.append(line.rstrip("\n"))
4120 +
4121 + if bash_command_not_found_re.match(line) is not None and \
4122 + command_not_found_exclude_re.search(line) is None:
4123 + bash_command_not_found.append(line.rstrip("\n"))
4124 +
4125 + if helper_missing_file_re.match(line) is not None:
4126 + helper_missing_file.append(line.rstrip("\n"))
4127 +
4128 + if configure_opts_warn_re.match(line) is not None:
4129 + configure_opts_warn.append(line.rstrip("\n"))
4130 +
4131 + if make_jobserver_re.match(line) is not None:
4132 + make_jobserver.append(line.rstrip("\n"))
4133 +
4134 + finally:
4135 + f.close()
4136 +
4137 + def _eqawarn(lines):
4138 + for line in lines:
4139 + eqawarn(line, phase="install", key=mysettings.mycpv, out=out)
4140 + wrap_width = 70
4141 +
4142 + if am_maintainer_mode:
4143 + msg = [_("QA Notice: Automake \"maintainer mode\" detected:")]
4144 + msg.append("")
4145 + msg.extend("\t" + line for line in am_maintainer_mode)
4146 + msg.append("")
4147 + msg.extend(wrap(_(
4148 + "If you patch Makefile.am, "
4149 + "configure.in, or configure.ac then you "
4150 + "should use autotools.eclass and "
4151 + "eautomake or eautoreconf. Exceptions "
4152 + "are limited to system packages "
4153 + "for which it is impossible to run "
4154 + "autotools during stage building. "
4155 + "See http://www.gentoo.org/p"
4156 + "roj/en/qa/autofailure.xml for more information."),
4157 + wrap_width))
4158 + _eqawarn(msg)
4159 +
4160 + if bash_command_not_found:
4161 + msg = [_("QA Notice: command not found:")]
4162 + msg.append("")
4163 + msg.extend("\t" + line for line in bash_command_not_found)
4164 + _eqawarn(msg)
4165 +
4166 + if helper_missing_file:
4167 + msg = [_("QA Notice: file does not exist:")]
4168 + msg.append("")
4169 + msg.extend("\t" + line[4:] for line in helper_missing_file)
4170 + _eqawarn(msg)
4171 +
4172 + if configure_opts_warn:
4173 + msg = [_("QA Notice: Unrecognized configure options:")]
4174 + msg.append("")
4175 + msg.extend("\t" + line for line in configure_opts_warn)
4176 + _eqawarn(msg)
4177 +
4178 + if make_jobserver:
4179 + msg = [_("QA Notice: make jobserver unavailable:")]
4180 + msg.append("")
4181 + msg.extend("\t" + line for line in make_jobserver)
4182 + _eqawarn(msg)
4183 +
4184 +def _post_src_install_chost_fix(settings):
4185 + """
4186 + It's possible that the ebuild has changed the
4187 + CHOST variable, so revert it to the initial
4188 + setting.
4189 + """
4190 + if settings.get('CATEGORY') == 'virtual':
4191 + return
4192 +
4193 + chost = settings.get('CHOST')
4194 + if chost:
4195 + write_atomic(os.path.join(settings['PORTAGE_BUILDDIR'],
4196 + 'build-info', 'CHOST'), chost + '\n')
4197 +
4198 +_vdb_use_conditional_keys = ('DEPEND', 'LICENSE', 'PDEPEND',
4199 + 'PROPERTIES', 'PROVIDE', 'RDEPEND', 'RESTRICT',)
4200 +_vdb_use_conditional_atoms = frozenset(['DEPEND', 'PDEPEND', 'RDEPEND'])
4201 +
4202 +def _post_src_install_uid_fix(mysettings, out=None):
4203 + """
4204 + Files in $D with user and group bits that match the "portage"
4205 + user or group are automatically mapped to PORTAGE_INST_UID and
4206 + PORTAGE_INST_GID if necessary. The chown system call may clear
4207 + S_ISUID and S_ISGID bits, so those bits are restored if
4208 + necessary.
4209 + """
4210 +
4211 + os = _os_merge
4212 +
4213 + inst_uid = int(mysettings["PORTAGE_INST_UID"])
4214 + inst_gid = int(mysettings["PORTAGE_INST_GID"])
4215 +
4216 + if bsd_chflags:
4217 + # Temporarily remove all of the flags in order to avoid EPERM errors.
4218 + os.system("mtree -c -p %s -k flags > %s" % \
4219 + (_shell_quote(mysettings["D"]),
4220 + _shell_quote(os.path.join(mysettings["T"], "bsdflags.mtree"))))
4221 + os.system("chflags -R noschg,nouchg,nosappnd,nouappnd %s" % \
4222 + (_shell_quote(mysettings["D"]),))
4223 + os.system("chflags -R nosunlnk,nouunlnk %s 2>/dev/null" % \
4224 + (_shell_quote(mysettings["D"]),))
4225 +
4226 + destdir = mysettings["D"]
4227 + unicode_errors = []
4228 +
4229 + while True:
4230 +
4231 + unicode_error = False
4232 + size = 0
4233 + counted_inodes = set()
4234 +
4235 + for parent, dirs, files in os.walk(destdir):
4236 + try:
4237 + parent = _unicode_decode(parent,
4238 + encoding=_encodings['merge'], errors='strict')
4239 + except UnicodeDecodeError:
4240 + new_parent = _unicode_decode(parent,
4241 + encoding=_encodings['merge'], errors='replace')
4242 + new_parent = _unicode_encode(new_parent,
4243 + encoding=_encodings['merge'], errors='backslashreplace')
4244 + new_parent = _unicode_decode(new_parent,
4245 + encoding=_encodings['merge'], errors='replace')
4246 + os.rename(parent, new_parent)
4247 + unicode_error = True
4248 + unicode_errors.append(new_parent[len(destdir):])
4249 + break
4250 +
4251 + for fname in chain(dirs, files):
4252 + try:
4253 + fname = _unicode_decode(fname,
4254 + encoding=_encodings['merge'], errors='strict')
4255 + except UnicodeDecodeError:
4256 + fpath = _os.path.join(
4257 + parent.encode(_encodings['merge']), fname)
4258 + new_fname = _unicode_decode(fname,
4259 + encoding=_encodings['merge'], errors='replace')
4260 + new_fname = _unicode_encode(new_fname,
4261 + encoding=_encodings['merge'], errors='backslashreplace')
4262 + new_fname = _unicode_decode(new_fname,
4263 + encoding=_encodings['merge'], errors='replace')
4264 + new_fpath = os.path.join(parent, new_fname)
4265 + os.rename(fpath, new_fpath)
4266 + unicode_error = True
4267 + unicode_errors.append(new_fpath[len(destdir):])
4268 + fname = new_fname
4269 + fpath = new_fpath
4270 + else:
4271 + fpath = os.path.join(parent, fname)
4272 +
4273 + mystat = os.lstat(fpath)
4274 + if stat.S_ISREG(mystat.st_mode) and \
4275 + mystat.st_ino not in counted_inodes:
4276 + counted_inodes.add(mystat.st_ino)
4277 + size += mystat.st_size
4278 + if mystat.st_uid != portage_uid and \
4279 + mystat.st_gid != portage_gid:
4280 + continue
4281 + myuid = -1
4282 + mygid = -1
4283 + if mystat.st_uid == portage_uid:
4284 + myuid = inst_uid
4285 + if mystat.st_gid == portage_gid:
4286 + mygid = inst_gid
4287 + apply_secpass_permissions(
4288 + _unicode_encode(fpath, encoding=_encodings['merge']),
4289 + uid=myuid, gid=mygid,
4290 + mode=mystat.st_mode, stat_cached=mystat,
4291 + follow_links=False)
4292 +
4293 + if unicode_error:
4294 + break
4295 +
4296 + if not unicode_error:
4297 + break
4298 +
4299 + if unicode_errors:
4300 + from portage.elog.messages import eerror
4301 + for l in _merge_unicode_error(unicode_errors):
4302 + eerror(l, phase='install', key=mysettings.mycpv, out=out)
4303 +
4304 + build_info_dir = os.path.join(mysettings['PORTAGE_BUILDDIR'],
4305 + 'build-info')
4306 +
4307 + codecs.open(_unicode_encode(os.path.join(build_info_dir,
4308 + 'SIZE'), encoding=_encodings['fs'], errors='strict'),
4309 + 'w', encoding=_encodings['repo.content'],
4310 + errors='strict').write(str(size) + '\n')
4311 +
4312 + codecs.open(_unicode_encode(os.path.join(build_info_dir,
4313 + 'BUILD_TIME'), encoding=_encodings['fs'], errors='strict'),
4314 + 'w', encoding=_encodings['repo.content'],
4315 + errors='strict').write(str(int(time.time())) + '\n')
4316 +
4317 + use = frozenset(mysettings['PORTAGE_USE'].split())
4318 + for k in _vdb_use_conditional_keys:
4319 + v = mysettings.configdict['pkg'].get(k)
4320 + if v is None:
4321 + continue
4322 + v = paren_reduce(v)
4323 + v = use_reduce(v, uselist=use)
4324 + v = paren_normalize(v)
4325 + v = paren_enclose(v)
4326 + if not v:
4327 + continue
4328 + if v in _vdb_use_conditional_atoms:
4329 + v_split = []
4330 + for x in v.split():
4331 + try:
4332 + x = Atom(x)
4333 + except InvalidAtom:
4334 + v_split.append(x)
4335 + else:
4336 + v_split.append(str(x.evaluate_conditionals(use)))
4337 + v = ' '.join(v_split)
4338 + codecs.open(_unicode_encode(os.path.join(build_info_dir,
4339 + k), encoding=_encodings['fs'], errors='strict'),
4340 + mode='w', encoding=_encodings['repo.content'],
4341 + errors='strict').write(v + '\n')
4342 +
4343 + if bsd_chflags:
4344 + # Restore all of the flags saved above.
4345 + os.system("mtree -e -p %s -U -k flags < %s > /dev/null" % \
4346 + (_shell_quote(mysettings["D"]),
4347 + _shell_quote(os.path.join(mysettings["T"], "bsdflags.mtree"))))
4348 +
4349 +def _merge_unicode_error(errors):
4350 + lines = []
4351 +
4352 + msg = _("This package installs one or more file names containing "
4353 + "characters that do not match your current locale "
4354 + "settings. The current setting for filesystem encoding is '%s'.") \
4355 + % _encodings['merge']
4356 + lines.extend(wrap(msg, 72))
4357 +
4358 + lines.append("")
4359 + errors.sort()
4360 + lines.extend("\t" + x for x in errors)
4361 + lines.append("")
4362 +
4363 + if _encodings['merge'].lower().replace('_', '').replace('-', '') != 'utf8':
4364 + msg = _("For best results, UTF-8 encoding is recommended. See "
4365 + "the Gentoo Linux Localization Guide for instructions "
4366 + "about how to configure your locale for UTF-8 encoding:")
4367 + lines.extend(wrap(msg, 72))
4368 + lines.append("")
4369 + lines.append("\t" + \
4370 + "http://www.gentoo.org/doc/en/guide-localization.xml")
4371 + lines.append("")
4372 +
4373 + return lines
4374 +
4375 +def _post_pkg_preinst_cmd(mysettings):
4376 + """
4377 + Post phase logic and tasks that have been factored out of
4378 + ebuild.sh. Call preinst_mask last so that INSTALL_MASK can
4379 + can be used to wipe out any gmon.out files created during
4380 + previous functions (in case any tools were built with -pg
4381 + in CFLAGS).
4382 + """
4383 +
4384 + portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
4385 + misc_sh_binary = os.path.join(portage_bin_path,
4386 + os.path.basename(MISC_SH_BINARY))
4387 +
4388 + mysettings["EBUILD_PHASE"] = ""
4389 + global _post_phase_cmds
4390 + myargs = [_shell_quote(misc_sh_binary)] + _post_phase_cmds["preinst"]
4391 +
4392 + return myargs
4393 +
4394 +def _post_pkg_postinst_cmd(mysettings):
4395 + """
4396 + Post phase logic and tasks that have been factored out of
4397 + build.sh.
4398 + """
4399 +
4400 + portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
4401 + misc_sh_binary = os.path.join(portage_bin_path,
4402 + os.path.basename(MISC_SH_BINARY))
4403 +
4404 + mysettings["EBUILD_PHASE"] = ""
4405 + global _post_phase_cmds
4406 + myargs = [_shell_quote(misc_sh_binary)] + _post_phase_cmds["postinst"]
4407 +
4408 + return myargs
4409 +
4410 +def _spawn_misc_sh(mysettings, commands, phase=None, **kwargs):
4411 + """
4412 + @param mysettings: the ebuild config
4413 + @type mysettings: config
4414 + @param commands: a list of function names to call in misc-functions.sh
4415 + @type commands: list
4416 + @rtype: int
4417 + @returns: the return value from the spawn() call
4418 + """
4419 +
4420 + # Note: PORTAGE_BIN_PATH may differ from the global
4421 + # constant when portage is reinstalling itself.
4422 + portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
4423 + misc_sh_binary = os.path.join(portage_bin_path,
4424 + os.path.basename(MISC_SH_BINARY))
4425 + mycommand = " ".join([_shell_quote(misc_sh_binary)] + commands)
4426 + _doebuild_exit_status_unlink(
4427 + mysettings.get("EBUILD_EXIT_STATUS_FILE"))
4428 + debug = mysettings.get("PORTAGE_DEBUG") == "1"
4429 + logfile = mysettings.get("PORTAGE_LOG_FILE")
4430 + mysettings.pop("EBUILD_PHASE", None)
4431 + try:
4432 + rval = spawn(mycommand, mysettings, debug=debug,
4433 + logfile=logfile, **kwargs)
4434 + finally:
4435 + pass
4436 +
4437 + msg = _doebuild_exit_status_check(phase, mysettings)
4438 + if msg:
4439 + if rval == os.EX_OK:
4440 + rval = 1
4441 + for l in wrap(msg, 72):
4442 + eerror(l, phase=phase, key=mysettings.mycpv)
4443 +
4444 + return rval
4445
4446
4447 Property changes on: main/trunk/pym/portage/package/ebuild/doebuild.py
4448 ___________________________________________________________________
4449 Added: svn:keywords
4450 + Id
4451
4452 Modified: main/trunk/pym/portage/package/ebuild/fetch.py
4453 ===================================================================
4454 --- main/trunk/pym/portage/package/ebuild/fetch.py 2010-02-24 21:27:43 UTC (rev 15447)
4455 +++ main/trunk/pym/portage/package/ebuild/fetch.py 2010-02-25 03:37:29 UTC (rev 15448)
4456 @@ -15,7 +15,13 @@
4457 import stat
4458 import sys
4459
4460 -from portage import check_config_instance, doebuild_environment, OrderedDict, os, prepare_build_dirs, selinux, _encodings, _shell_quote, _unicode_encode
4461 +
4462 +import portage
4463 +portage.proxy.lazyimport.lazyimport(globals(),
4464 + 'portage.package.ebuild.config:check_config_instance,config',
4465 +)
4466 +
4467 +from portage import doebuild_environment, OrderedDict, os, prepare_build_dirs, selinux, _encodings, _shell_quote, _unicode_encode
4468 from portage.checksum import perform_md5, verify_all
4469 from portage.const import BASH_BINARY, CUSTOM_MIRRORS_FILE, EBUILD_SH_BINARY, GLOBAL_CONFIG_PATH
4470 from portage.data import portage_gid, portage_uid, secpass, userpriv_groups
4471 @@ -24,7 +30,6 @@
4472 from portage.locks import lockfile, unlockfile
4473 from portage.manifest import Manifest
4474 from portage.output import colorize, EOutput
4475 -from portage.package.ebuild.config import config
4476 from portage.util import apply_recursive_permissions, apply_secpass_permissions, ensure_dirs, grabdict, shlex_split, varexpand, writemsg, writemsg_level, writemsg_stdout
4477 from portage.process import spawn
4478
4479
4480 Added: main/trunk/pym/portage/package/ebuild/prepare_build_dirs.py
4481 ===================================================================
4482 --- main/trunk/pym/portage/package/ebuild/prepare_build_dirs.py (rev 0)
4483 +++ main/trunk/pym/portage/package/ebuild/prepare_build_dirs.py 2010-02-25 03:37:29 UTC (rev 15448)
4484 @@ -0,0 +1,304 @@
4485 +# Copyright 2010 Gentoo Foundation
4486 +# Distributed under the terms of the GNU General Public License v2
4487 +# $Id$
4488 +
4489 +__all__ = ['prepare_build_dirs']
4490 +
4491 +import codecs
4492 +import errno
4493 +import shutil
4494 +import stat
4495 +import time
4496 +
4497 +from portage import os, _encodings, _unicode_encode, _unicode_decode
4498 +from portage.data import portage_gid, portage_uid, secpass
4499 +from portage.exception import DirectoryNotFound, FileNotFound, \
4500 + OperationNotPermitted, PermissionDenied, PortageException
4501 +from portage.localization import _
4502 +from portage.output import colorize
4503 +from portage.util import apply_recursive_permissions, \
4504 + apply_secpass_permissions, ensure_dirs, writemsg
4505 +
4506 +def prepare_build_dirs(myroot, mysettings, cleanup):
4507 +
4508 + clean_dirs = [mysettings["HOME"]]
4509 +
4510 + # We enable cleanup when we want to make sure old cruft (such as the old
4511 + # environment) doesn't interfere with the current phase.
4512 + if cleanup:
4513 + clean_dirs.append(mysettings["T"])
4514 +
4515 + for clean_dir in clean_dirs:
4516 + try:
4517 + shutil.rmtree(clean_dir)
4518 + except OSError as oe:
4519 + if errno.ENOENT == oe.errno:
4520 + pass
4521 + elif errno.EPERM == oe.errno:
4522 + writemsg("%s\n" % oe, noiselevel=-1)
4523 + writemsg(_("Operation Not Permitted: rmtree('%s')\n") % \
4524 + clean_dir, noiselevel=-1)
4525 + return 1
4526 + else:
4527 + raise
4528 +
4529 + def makedirs(dir_path):
4530 + try:
4531 + os.makedirs(dir_path)
4532 + except OSError as oe:
4533 + if errno.EEXIST == oe.errno:
4534 + pass
4535 + elif errno.EPERM == oe.errno:
4536 + writemsg("%s\n" % oe, noiselevel=-1)
4537 + writemsg(_("Operation Not Permitted: makedirs('%s')\n") % \
4538 + dir_path, noiselevel=-1)
4539 + return False
4540 + else:
4541 + raise
4542 + return True
4543 +
4544 + mysettings["PKG_LOGDIR"] = os.path.join(mysettings["T"], "logging")
4545 +
4546 + mydirs = [os.path.dirname(mysettings["PORTAGE_BUILDDIR"])]
4547 + mydirs.append(os.path.dirname(mydirs[-1]))
4548 +
4549 + try:
4550 + for mydir in mydirs:
4551 + ensure_dirs(mydir)
4552 + apply_secpass_permissions(mydir,
4553 + gid=portage_gid, uid=portage_uid, mode=0o70, mask=0)
4554 + for dir_key in ("PORTAGE_BUILDDIR", "HOME", "PKG_LOGDIR", "T"):
4555 + """These directories don't necessarily need to be group writable.
4556 + However, the setup phase is commonly run as a privileged user prior
4557 + to the other phases being run by an unprivileged user. Currently,
4558 + we use the portage group to ensure that the unprivleged user still
4559 + has write access to these directories in any case."""
4560 + ensure_dirs(mysettings[dir_key], mode=0o775)
4561 + apply_secpass_permissions(mysettings[dir_key],
4562 + uid=portage_uid, gid=portage_gid)
4563 + except PermissionDenied as e:
4564 + writemsg(_("Permission Denied: %s\n") % str(e), noiselevel=-1)
4565 + return 1
4566 + except OperationNotPermitted as e:
4567 + writemsg(_("Operation Not Permitted: %s\n") % str(e), noiselevel=-1)
4568 + return 1
4569 + except FileNotFound as e:
4570 + writemsg(_("File Not Found: '%s'\n") % str(e), noiselevel=-1)
4571 + return 1
4572 +
4573 + # Reset state for things like noauto and keepwork in FEATURES.
4574 + for x in ('.die_hooks',):
4575 + try:
4576 + os.unlink(os.path.join(mysettings['PORTAGE_BUILDDIR'], x))
4577 + except OSError:
4578 + pass
4579 +
4580 + _prepare_workdir(mysettings)
4581 + if mysettings.get('EBUILD_PHASE') != 'fetch':
4582 + # Avoid spurious permissions adjustments when fetching with
4583 + # a temporary PORTAGE_TMPDIR setting (for fetchonly).
4584 + _prepare_features_dirs(mysettings)
4585 +
4586 +def _adjust_perms_msg(settings, msg):
4587 +
4588 + def write(msg):
4589 + writemsg(msg, noiselevel=-1)
4590 +
4591 + background = settings.get("PORTAGE_BACKGROUND") == "1"
4592 + log_path = settings.get("PORTAGE_LOG_FILE")
4593 + log_file = None
4594 +
4595 + if background and log_path is not None:
4596 + try:
4597 + log_file = codecs.open(_unicode_encode(log_path,
4598 + encoding=_encodings['fs'], errors='strict'),
4599 + mode='a', encoding=_encodings['content'], errors='replace')
4600 + except IOError:
4601 + def write(msg):
4602 + pass
4603 + else:
4604 + def write(msg):
4605 + log_file.write(_unicode_decode(msg))
4606 + log_file.flush()
4607 +
4608 + try:
4609 + write(msg)
4610 + finally:
4611 + if log_file is not None:
4612 + log_file.close()
4613 +
4614 +def _prepare_features_dirs(mysettings):
4615 +
4616 + features_dirs = {
4617 + "ccache":{
4618 + "path_dir": "/usr/lib/ccache/bin",
4619 + "basedir_var":"CCACHE_DIR",
4620 + "default_dir":os.path.join(mysettings["PORTAGE_TMPDIR"], "ccache"),
4621 + "always_recurse":False},
4622 + "distcc":{
4623 + "path_dir": "/usr/lib/distcc/bin",
4624 + "basedir_var":"DISTCC_DIR",
4625 + "default_dir":os.path.join(mysettings["BUILD_PREFIX"], ".distcc"),
4626 + "subdirs":("lock", "state"),
4627 + "always_recurse":True}
4628 + }
4629 + dirmode = 0o2070
4630 + filemode = 0o60
4631 + modemask = 0o2
4632 + restrict = mysettings.get("PORTAGE_RESTRICT","").split()
4633 + droppriv = secpass >= 2 and \
4634 + "userpriv" in mysettings.features and \
4635 + "userpriv" not in restrict
4636 + for myfeature, kwargs in features_dirs.items():
4637 + if myfeature in mysettings.features:
4638 + failure = False
4639 + basedir = mysettings.get(kwargs["basedir_var"])
4640 + if basedir is None or not basedir.strip():
4641 + basedir = kwargs["default_dir"]
4642 + mysettings[kwargs["basedir_var"]] = basedir
4643 + try:
4644 + path_dir = kwargs["path_dir"]
4645 + if not os.path.isdir(path_dir):
4646 + raise DirectoryNotFound(path_dir)
4647 +
4648 + mydirs = [mysettings[kwargs["basedir_var"]]]
4649 + if "subdirs" in kwargs:
4650 + for subdir in kwargs["subdirs"]:
4651 + mydirs.append(os.path.join(basedir, subdir))
4652 + for mydir in mydirs:
4653 + modified = ensure_dirs(mydir)
4654 + # Generally, we only want to apply permissions for
4655 + # initial creation. Otherwise, we don't know exactly what
4656 + # permissions the user wants, so should leave them as-is.
4657 + droppriv_fix = False
4658 + if droppriv:
4659 + st = os.stat(mydir)
4660 + if st.st_gid != portage_gid or \
4661 + not dirmode == (stat.S_IMODE(st.st_mode) & dirmode):
4662 + droppriv_fix = True
4663 + if not droppriv_fix:
4664 + # Check permissions of files in the directory.
4665 + for filename in os.listdir(mydir):
4666 + try:
4667 + subdir_st = os.lstat(
4668 + os.path.join(mydir, filename))
4669 + except OSError:
4670 + continue
4671 + if subdir_st.st_gid != portage_gid or \
4672 + ((stat.S_ISDIR(subdir_st.st_mode) and \
4673 + not dirmode == (stat.S_IMODE(subdir_st.st_mode) & dirmode))):
4674 + droppriv_fix = True
4675 + break
4676 +
4677 + if droppriv_fix:
4678 + _adjust_perms_msg(mysettings,
4679 + colorize("WARN", " * ") + \
4680 + _("Adjusting permissions "
4681 + "for FEATURES=userpriv: '%s'\n") % mydir)
4682 + elif modified:
4683 + _adjust_perms_msg(mysettings,
4684 + colorize("WARN", " * ") + \
4685 + _("Adjusting permissions "
4686 + "for FEATURES=%s: '%s'\n") % (myfeature, mydir))
4687 +
4688 + if modified or kwargs["always_recurse"] or droppriv_fix:
4689 + def onerror(e):
4690 + raise # The feature is disabled if a single error
4691 + # occurs during permissions adjustment.
4692 + if not apply_recursive_permissions(mydir,
4693 + gid=portage_gid, dirmode=dirmode, dirmask=modemask,
4694 + filemode=filemode, filemask=modemask, onerror=onerror):
4695 + raise OperationNotPermitted(
4696 + _("Failed to apply recursive permissions for the portage group."))
4697 +
4698 + except DirectoryNotFound as e:
4699 + failure = True
4700 + writemsg(_("\n!!! Directory does not exist: '%s'\n") % \
4701 + (e,), noiselevel=-1)
4702 + writemsg(_("!!! Disabled FEATURES='%s'\n") % myfeature,
4703 + noiselevel=-1)
4704 +
4705 + except PortageException as e:
4706 + failure = True
4707 + writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
4708 + writemsg(_("!!! Failed resetting perms on %s='%s'\n") % \
4709 + (kwargs["basedir_var"], basedir), noiselevel=-1)
4710 + writemsg(_("!!! Disabled FEATURES='%s'\n") % myfeature,
4711 + noiselevel=-1)
4712 +
4713 + if failure:
4714 + mysettings.features.remove(myfeature)
4715 + mysettings['FEATURES'] = ' '.join(sorted(mysettings.features))
4716 + time.sleep(5)
4717 +
4718 +def _prepare_workdir(mysettings):
4719 + workdir_mode = 0o700
4720 + try:
4721 + mode = mysettings["PORTAGE_WORKDIR_MODE"]
4722 + if mode.isdigit():
4723 + parsed_mode = int(mode, 8)
4724 + elif mode == "":
4725 + raise KeyError()
4726 + else:
4727 + raise ValueError()
4728 + if parsed_mode & 0o7777 != parsed_mode:
4729 + raise ValueError("Invalid file mode: %s" % mode)
4730 + else:
4731 + workdir_mode = parsed_mode
4732 + except KeyError as e:
4733 + writemsg(_("!!! PORTAGE_WORKDIR_MODE is unset, using %s.\n") % oct(workdir_mode))
4734 + except ValueError as e:
4735 + if len(str(e)) > 0:
4736 + writemsg("%s\n" % e)
4737 + writemsg(_("!!! Unable to parse PORTAGE_WORKDIR_MODE='%s', using %s.\n") % \
4738 + (mysettings["PORTAGE_WORKDIR_MODE"], oct(workdir_mode)))
4739 + mysettings["PORTAGE_WORKDIR_MODE"] = oct(workdir_mode).replace('o', '')
4740 + try:
4741 + apply_secpass_permissions(mysettings["WORKDIR"],
4742 + uid=portage_uid, gid=portage_gid, mode=workdir_mode)
4743 + except FileNotFound:
4744 + pass # ebuild.sh will create it
4745 +
4746 + if mysettings.get("PORT_LOGDIR", "") == "":
4747 + while "PORT_LOGDIR" in mysettings:
4748 + del mysettings["PORT_LOGDIR"]
4749 + if "PORT_LOGDIR" in mysettings:
4750 + try:
4751 + modified = ensure_dirs(mysettings["PORT_LOGDIR"])
4752 + if modified:
4753 + apply_secpass_permissions(mysettings["PORT_LOGDIR"],
4754 + uid=portage_uid, gid=portage_gid, mode=0o2770)
4755 + except PortageException as e:
4756 + writemsg("!!! %s\n" % str(e), noiselevel=-1)
4757 + writemsg(_("!!! Permission issues with PORT_LOGDIR='%s'\n") % \
4758 + mysettings["PORT_LOGDIR"], noiselevel=-1)
4759 + writemsg(_("!!! Disabling logging.\n"), noiselevel=-1)
4760 + while "PORT_LOGDIR" in mysettings:
4761 + del mysettings["PORT_LOGDIR"]
4762 + if "PORT_LOGDIR" in mysettings and \
4763 + os.access(mysettings["PORT_LOGDIR"], os.W_OK):
4764 + logid_path = os.path.join(mysettings["PORTAGE_BUILDDIR"], ".logid")
4765 + if not os.path.exists(logid_path):
4766 + open(_unicode_encode(logid_path), 'w')
4767 + logid_time = _unicode_decode(time.strftime("%Y%m%d-%H%M%S",
4768 + time.gmtime(os.stat(logid_path).st_mtime)),
4769 + encoding=_encodings['content'], errors='replace')
4770 +
4771 + if "split-log" in mysettings.features:
4772 + mysettings["PORTAGE_LOG_FILE"] = os.path.join(
4773 + mysettings["PORT_LOGDIR"], "build", "%s/%s:%s.log" % \
4774 + (mysettings["CATEGORY"], mysettings["PF"], logid_time))
4775 + else:
4776 + mysettings["PORTAGE_LOG_FILE"] = os.path.join(
4777 + mysettings["PORT_LOGDIR"], "%s:%s:%s.log" % \
4778 + (mysettings["CATEGORY"], mysettings["PF"], logid_time))
4779 +
4780 + ensure_dirs(os.path.dirname(mysettings["PORTAGE_LOG_FILE"]))
4781 +
4782 + else:
4783 + # NOTE: When sesandbox is enabled, the local SELinux security policies
4784 + # may not allow output to be piped out of the sesandbox domain. The
4785 + # current policy will allow it to work when a pty is available, but
4786 + # not through a normal pipe. See bug #162404.
4787 + mysettings["PORTAGE_LOG_FILE"] = os.path.join(
4788 + mysettings["T"], "build.log")
4789
4790
4791 Property changes on: main/trunk/pym/portage/package/ebuild/prepare_build_dirs.py
4792 ___________________________________________________________________
4793 Added: svn:keywords
4794 + Id
4795
4796 Modified: main/trunk/pym/portage/tests/ebuild/test_pty_eof.py
4797 ===================================================================
4798 --- main/trunk/pym/portage/tests/ebuild/test_pty_eof.py 2010-02-24 21:27:43 UTC (rev 15447)
4799 +++ main/trunk/pym/portage/tests/ebuild/test_pty_eof.py 2010-02-25 03:37:29 UTC (rev 15448)
4800 @@ -4,6 +4,7 @@
4801
4802 import portage
4803 from portage.tests import TestCase
4804 +from portage.package.ebuild._pty import _can_test_pty_eof, _test_pty_eof
4805
4806 class PtyEofTestCase(TestCase):
4807
4808 @@ -13,8 +14,8 @@
4809 # Since it might not be fixed, mark as todo.
4810 self.todo = True
4811 # The result is only valid if openpty does not raise EnvironmentError.
4812 - if portage._can_test_pty_eof():
4813 + if _can_test_pty_eof():
4814 try:
4815 - self.assertEqual(portage._test_pty_eof(), True)
4816 + self.assertEqual(_test_pty_eof(), True)
4817 except EnvironmentError:
4818 pass