Merged from trunk 7372:7396
authorFabian Groffen <grobian@gentoo.org>
Wed, 25 Jul 2007 20:19:58 +0000 (20:19 -0000)
committerFabian Groffen <grobian@gentoo.org>
Wed, 25 Jul 2007 20:19:58 +0000 (20:19 -0000)
   +------------------------------------------------------------------------+
   | 7373      | Drop privileges in the "depend" phase regardless of        |
   | zmedico   | FEATURES and RESTRICT since that phase should never need   |
   |           | special privileges. Thanks to swegener for the initial     |
   |           | patch.                                                     |
   |-----------+------------------------------------------------------------|
   | 7375      | Enable FEATURES=userfetch by default.                      |
   | zmedico   |                                                            |
   |-----------+------------------------------------------------------------|
   | 7377      | Add sfperms and strict to the default FEATURES since       |
   | zmedico   | they're already in the base profile's make.defaults.       |
   |-----------+------------------------------------------------------------|
   | 7379      | Add FEATURES=fakeroot support which causes install and     |
   | zmedico   | package phases to run inside fakeroot when a non-root user |
   |           | runs the ebuild command. Thanks to swegener for the        |
   |           | initial patch.                                             |
   |-----------+------------------------------------------------------------|
   | 7381      | For bug #186337, show an ewarn message if                  |
   | zmedico   | FEATURES=installsources is enabled but debugedit is not    |
   |           | installed. Also document installsources and splitdebug in  |
   |           | make.conf.example.                                         |
   |-----------+------------------------------------------------------------|
   | 7383      | Fix make.conf.example rejects.                             |
   | zmedico   |                                                            |
   |-----------+------------------------------------------------------------|
   | 7385      | Add droppriv keyword for the depend phase.                 |
   | zmedico   |                                                            |
   |-----------+------------------------------------------------------------|
   | 7387      | Add droppriv keyword for the depend phase (last one).      |
   | zmedico   |                                                            |
   |-----------+------------------------------------------------------------|
   | 7389      | Use a select loop for moving input and ouput when logging  |
   | zmedico   | is enabled in portage.spawn().                             |
   |-----------+------------------------------------------------------------|
   | 7390      | Use the hardcoded variables from portage.const rather than |
   | WarnerBro | strings that are apt to change, fix spacing.               |
   |-----------+------------------------------------------------------------|
   | 7391      | Use blocking mode for writes since we'd rather block than  |
   | zmedico   | trigger a EWOULDBLOCK error.                               |
   |-----------+------------------------------------------------------------|
   | 7392      | CACHE_PATH starts with / and therefore isn't compatible    |
   | zmedico   | with os.path.join().                                       |
   |-----------+------------------------------------------------------------|
   | 7393      | Set O_NONBLOCK just for read calls (uses fewer fcntl       |
   | zmedico   | calls).                                                    |
   |-----------+------------------------------------------------------------|
   | 7394      | For bug #186386, pass stdin directly to spawned processes  |
   | zmedico   | (even when their output goes through a pty) so that Ctrl+Z |
   |           | works as on would expect.)                                 |
   |-----------+------------------------------------------------------------|
   | 7396      | use ${MAKE:-make} rather than make in einstall()           |
   | SpankMan  |                                                            |
   +------------------------------------------------------------------------+

svn path=/main/branches/prefix/; revision=7398

bin/ebuild.sh
bin/prepstrip
cnf/make.conf
cnf/make.conf.sparc-fbsd.diff
cnf/make.conf.x86-fbsd.diff
cnf/make.globals
man/make.conf.5
pym/portage/__init__.py
pym/portage/dbapi/porttree.py
pym/portage/process.py

index 483755aa1528c1a74ad97936206e8a707088b3ee..6db4410ca1d59b64380a4159bd95800e543de3db 100755 (executable)
@@ -547,7 +547,7 @@ einstall() {
 
        if [ -f ./[mM]akefile -o -f ./GNUmakefile ] ; then
                if [ "${PORTAGE_DEBUG}" == "1" ]; then
-                       make -n prefix="${ED}/usr" \
+                       ${MAKE:-make} -n prefix="${ED}/usr" \
                                datadir="${ED}/usr/share" \
                                infodir="${ED}/usr/share/info" \
                                localstatedir="${ED}/var/lib" \
@@ -556,7 +556,7 @@ einstall() {
                                ${LOCAL_EXTRA_EINSTALL} \
                                "$@" install
                fi
-               make prefix="${ED}/usr" \
+               ${MAKE:-make} prefix="${ED}/usr" \
                        datadir="${ED}/usr/share" \
                        infodir="${ED}/usr/share/info" \
                        localstatedir="${ED}/var/lib" \
@@ -1664,8 +1664,8 @@ if [ -n "${myarg}" ] && \
        unset myarg
        # Save current environment and touch a success file. (echo for success)
        umask 002
-       set | egrep -v "^SANDBOX_" > "${T}/environment" 2>/dev/null
-       export | egrep -v "^declare -x SANDBOX_" | \
+       set | egrep -v -e "^SANDBOX_" -e "^LD_PRELOAD=" -e "^FAKEROOTKEY=" > "${T}/environment" 2>/dev/null
+       export | egrep -v -e "^declare -x SANDBOX_" -e "^declare -x LD_PRELOAD=" -e "^declare -x FAKEROOTKEY=" | \
                sed 's:^declare -rx:declare -x:' >> "${T}/environment" 2>/dev/null
        chown ${PORTAGE_USER:-portage}:${PORTAGE_GROUP:-portage} "${T}/environment" &>/dev/null
        chmod g+w "${T}/environment" &>/dev/null
index 8fce32b1c4cfbfd081adcc305acf97a8ac4e2102..86850cc872771ae98178a3adeb81f3dae3acc33a 100755 (executable)
@@ -25,6 +25,11 @@ type -P -- ${OBJCOPY} > /dev/null || OBJCOPY=objcopy
 export SAFE_STRIP_FLAGS="--strip-unneeded"
 export PORTAGE_STRIP_FLAGS=${PORTAGE_STRIP_FLAGS-${SAFE_STRIP_FLAGS} -R .comment}
 
+if hasq installsources ${FEATURES} && ! type -P debugedit >/dev/null ; then
+       ewarn "FEATURES=installsources is enabled but the debugedit binary could not"
+       ewarn "be found. This feature will not work unless debugedit is installed!"
+fi
+
 save_elf_sources() {
        hasq installsources ${FEATURES} || return 0
        type -P debugedit >/dev/null || return 0
index 73a4419285cadde8269774f8f8155f6e8dd21a9a..abe42f587ed4f19cd8aed73fce1ef6ec889d7959 100644 (file)
 #  'distlocks'   enables distfiles locking using fcntl or hardlinks. This
 #                is enabled by default. Tools exist to help clean the locks
 #                after crashes: /usr/lib/portage/bin/clean_locks.
+#  'installsources'
+#                Install source code into /usr/src/debug/${CATEGORY}/${PF}
+#                (also see 'splitdebug'). This feature works only if debugedit
+#                is installed and CFLAGS is set to include debug information
+#                (such as with the -ggdb flag).
 #  'test'        causes ebuilds to perform testing phases if they are capable
 #                of it. Some packages support this automatically via makefiles.
 #  'metadata-transfer'
 #  'parallel-fetch'
 #                do fetching in parallel to compilation
 #  'sandbox'     enables sandboxing when running emerge and ebuild.
+#  'splitdebug'  Prior to stripping ELF etdyn and etexec files, the debugging
+#                info is stored for later use by various debuggers.  This
+#                feature is disabled by 'nostrip'.  For installation of source
+#                code, see 'installsources'.
 #  'strict'      causes portage to react strongly to conditions that are
 #                potentially dangerous, like missing/incorrect Manifest files.
 #  'stricter'    causes portage to react strongly to conditions that may
index b3413da9ee6effbc05f2319bf171b446f4aaaea8..d71178abbaca6e9a8473dfb3319fbbc253ea7db9 100644 (file)
  
  # Portage Directories
  # ===================
-@@ -287,7 +294,8 @@
+@@ -279,7 +286,8 @@
  #  'notitles'    disables xterm titlebar updates (which contain status info). 
  #  'parallel-fetch'
  #                do fetching in parallel to compilation
 -#  'sandbox'     enables sandboxing when running emerge and ebuild.
 +#  'sandbox'     enables sandboxing when running emerge and ebuild. Doesn't
 +#                work on *BSD-based systems.
- #  'strict'      causes portage to react strongly to conditions that are
- #                potentially dangerous, like missing/incorrect Manifest files.
- #  'userfetch'   when portage is run as root, drop privileges to
+ #  'splitdebug'  Prior to stripping ELF etdyn and etexec files, the debugging
+ #                info is stored for later use by various debuggers.  This
+ #                feature is disabled by 'nostrip'.  For installation of source
index 6ce2c8090448143f049c3d337aff47727d5b9020..787bc35268fe5e162d52c9d722399cd7dba9010b 100644 (file)
  # Host and optimization settings 
  # ==============================
  #
-@@ -33,10 +42,34 @@
+@@ -33,10 +43,34 @@
  # package (and in some cases the libraries it uses) at default optimizations
  # before reporting errors to developers.
  #
 -# Please refer to the GCC manual for a list of possible values.
 +# -mtune=<cpu-type> means optimize code for the particular type of CPU without
 +# breaking compatibility with other CPUs.
-+#
+ #
+-#CFLAGS="-O2 -pipe"
 +# -march=<cpu-type> means to take full advantage of the ABI and instructions
 +# for the particular CPU; this will break compatibility with older CPUs (for
 +# example, -march=athlon-xp code will not run on a regular Athlon, and
 +# Pentium-M CPU's should not enable sse2 until at least gcc-3.4. Bug 50616. #
 +# ************************************************************************* #
  #
--#CFLAGS="-O2 -pipe"
 +# Decent examples:
- #
++#
 +#CFLAGS="-mtune=athlon-xp -O3 -pipe"
 +#CFLAGS="-march=pentium3 -O3 -pipe"
 +
  # If you set a CFLAGS above, then this line will set your default C++ flags to
  # the same settings.
  #CXXFLAGS="${CFLAGS}"
-@@ -61,7 +80,7 @@
+@@ -61,7 +95,7 @@
  # DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
  # IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
  #
  
  # Portage Directories
  # ===================
-@@ -268,7 +289,8 @@
+@@ -279,7 +313,8 @@
  #  'notitles'    disables xterm titlebar updates (which contain status info). 
  #  'parallel-fetch'
  #                do fetching in parallel to compilation
 -#  'sandbox'     enables sandboxing when running emerge and ebuild.
 +#  'sandbox'     enables sandboxing when running emerge and ebuild. Doesn't 
 +#                work on *BSD-based systems.
- #  'strict'      causes portage to react strongly to conditions that are
- #                potentially dangerous, like missing/incorrect Manifest files.
+ #  'splitdebug'  Prior to stripping ELF etdyn and etexec files, the debugging
+ #                info is stored for later use by various debuggers.  This
+ #                feature is disabled by 'nostrip'.  For installation of source
index f3336c8fe3a6bdd991823c6631df2be813b4e0c6..3997599bb530a1013a7f84440c1fa190340dc7d3 100644 (file)
@@ -33,7 +33,7 @@ FETCHCOMMAND="wget -t 5 -T 60 --passive-ftp -O \${DISTDIR}/\${FILE} \${URI}"
 RESUMECOMMAND="wget -c -t 5 -T 60 --passive-ftp -O \${DISTDIR}/\${FILE} \${URI}"
 
 # Default user options
-FEATURES="sandbox distlocks metadata-transfer unmerge-orphans"
+FEATURES="distlocks metadata-transfer sandbox sfperms strict unmerge-orphans userfetch"
 
 # Default chunksize for binhost comms
 PORTAGE_BINHOST_CHUNKSIZE="3000"
index 4cb5b8bad951bad88908e81943c3a0c6ce33432a..e1e11dafb18128a7364b740e02a44bd28129fc53 100644 (file)
@@ -169,6 +169,10 @@ strangely configured Samba server (oplocks off, NFS re\-export). A tool
 @PORTAGE_BASE@bin/clean_locks exists to help handle lock issues
 when a problem arises (normally due to a crash or disconnect).
 .TP
+.B fakeroot
+Enable fakeroot for the install and package phases when a non-root user runs
+the \fBebuild\fR(1) command.
+.TP
 .B fixpackages
 Runs the script that will fix the dependencies in all binary packages.  This is 
 run whenever packages are moved around in the portage tree.  Please note that this 
index 6f1df54ee50ad85d867c7a16d4b6d494286f7a67..4a3c661005fac022317f1423b741e12b39dd10de 100644 (file)
@@ -63,14 +63,14 @@ try:
 
        import portage.const
        from portage.const import VDB_PATH, PRIVATE_PATH, CACHE_PATH, DEPCACHE_PATH, \
-         USER_CONFIG_PATH, MODULES_FILE_PATH, CUSTOM_PROFILE_PATH, PORTAGE_BASE_PATH, \
-         PORTAGE_BIN_PATH, PORTAGE_PYM_PATH, PROFILE_PATH, LOCALE_DATA_PATH, \
-         EBUILD_SH_BINARY, SANDBOX_BINARY, BASH_BINARY, \
-         MOVE_BINARY, PRELINK_BINARY, WORLD_FILE, MAKE_CONF_FILE, MAKE_DEFAULTS_FILE, \
-         DEPRECATED_PROFILE_FILE, USER_VIRTUALS_FILE, EBUILD_SH_ENV_FILE, \
-         INVALID_ENV_FILE, CUSTOM_MIRRORS_FILE, CONFIG_MEMORY_FILE,\
-         INCREMENTALS, EAPI, MISC_SH_BINARY, REPO_NAME_LOC, REPO_NAME_FILE, \
-         EPREFIX
+               USER_CONFIG_PATH, MODULES_FILE_PATH, CUSTOM_PROFILE_PATH, PORTAGE_BASE_PATH, \
+               PORTAGE_BIN_PATH, PORTAGE_PYM_PATH, PROFILE_PATH, LOCALE_DATA_PATH, \
+               EBUILD_SH_BINARY, SANDBOX_BINARY, BASH_BINARY, \
+               MOVE_BINARY, PRELINK_BINARY, WORLD_FILE, MAKE_CONF_FILE, MAKE_DEFAULTS_FILE, \
+               DEPRECATED_PROFILE_FILE, USER_VIRTUALS_FILE, EBUILD_SH_ENV_FILE, \
+               INVALID_ENV_FILE, CUSTOM_MIRRORS_FILE, CONFIG_MEMORY_FILE,\
+               INCREMENTALS, EAPI, MISC_SH_BINARY, REPO_NAME_LOC, REPO_NAME_FILE, \
+               EPREFIX
 
        from portage.data import ostype, lchown, userland, secpass, uid, wheelgid, \
                                 portage_uid, portage_gid, userpriv_groups
@@ -1506,10 +1506,10 @@ class config(object):
                        return
 
                dir_mode_map = {
-                       "tmp"             :(-1,          01777, 0),
-                       "var/tmp"         :(-1,          01777, 0),
-                       "var/lib/portage" :(portage_gid, 02750, 02),
-                       "var/cache/edb"   :(portage_gid,  0755, 02)
+                       "tmp"             : (-1,          01777, 0),
+                       "var/tmp"         : (-1,          01777, 0),
+                       PRIVATE_PATH      : (portage_gid, 02750, 02),
+                       CACHE_PATH.lstrip(os.path.sep) : (portage_gid, 0755, 02)
                }
 
                for mypath, (gid, mode, modemask) in dir_mode_map.iteritems():
@@ -2335,7 +2335,7 @@ class config(object):
 
 # XXX This would be to replace getstatusoutput completely.
 # XXX Issue: cannot block execution. Deadlock condition.
-def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, **keywords):
+def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakeroot=0, **keywords):
        """
        Spawn a subprocess with extra portage-specific options.
        Optiosn include:
@@ -2363,6 +2363,8 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, **keyw
        @type droppriv: Boolean
        @param sesandbox: Enable SELinux Sandboxing (toggles a context switch)
        @type sesandbox: Boolean
+       @param fakeroot: Run this command with faked root privileges
+       @type fakeroot: Boolean
        @param keywords: Extra options encoded as a dict, to be passed to spawn
        @type keywords: Dictionary
        @rtype: Integer
@@ -2385,11 +2387,9 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, **keyw
        # pseudo-terminal that connects two domains.
        logfile = keywords.get("logfile")
        mypids = []
+       master_fd = None
        slave_fd = None
-       output_pid = None
-       input_pid = None
-       stdin_termios = None
-       stdin_fd = None
+       fd_pipes_orig = None
        if logfile:
                del keywords["logfile"]
                fd_pipes = keywords.get("fd_pipes")
@@ -2400,61 +2400,22 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, **keyw
                from pty import openpty
                master_fd, slave_fd = openpty()
                fd_pipes.setdefault(0, sys.stdin.fileno())
+               fd_pipes_orig = fd_pipes.copy()
                stdin_fd = fd_pipes[0]
                if os.isatty(stdin_fd):
-                       # Copy the termios attributes from stdin_fd to the slave_fd and put
-                       # the stdin_fd into raw mode with ECHO disabled.  The stdin
-                       # termios attributes are reverted before returning, or via the
-                       # atexit hook in portage.process when killed by a signal.
-                       import termios, tty
-                       stdin_termios = termios.tcgetattr(stdin_fd)
-                       tty.setraw(stdin_fd)
-                       term_attr = termios.tcgetattr(stdin_fd)
-                       term_attr[3] &= ~termios.ECHO
-                       termios.tcsetattr(stdin_fd, termios.TCSAFLUSH, term_attr)
-                       termios.tcsetattr(slave_fd, termios.TCSAFLUSH, stdin_termios)
                        from output import get_term_size, set_term_size
                        rows, columns = get_term_size()
                        set_term_size(rows, columns, slave_fd)
-                       pre_exec = keywords.get("pre_exec")
-                       def setup_ctty():
-                               os.setsid()
-                               # Make it into the "controlling terminal".
-                               import termios
-                               if hasattr(termios, "TIOCSCTTY"):
-                                       # BSD 4.3 approach
-                                       import fcntl
-                                       fcntl.ioctl(0, termios.TIOCSCTTY)
-                               else:
-                                       # SVR4 approach
-                                       fd = os.open(os.ttyname(0), os.O_RDWR)
-                                       for x in 0, 1, 2:
-                                               os.dup2(fd, x)
-                                       os.close(fd)
-                               if pre_exec:
-                                       pre_exec()
-                       keywords["pre_exec"] = setup_ctty
-               # tee will always exit with an IO error, so ignore it's stderr.
-               null_file = open('/dev/null', 'w')
-               mypids.extend(portage.process.spawn(['tee', '-i', '-a', logfile],
-                       returnpid=True, fd_pipes={0:master_fd, 1:fd_pipes[1],
-                       2:null_file.fileno()}))
-               output_pid = mypids[-1]
-               mypids.extend(portage.process.spawn(['cat'],
-                       returnpid=True, fd_pipes={0:fd_pipes[0], 1:master_fd,
-                       2:null_file.fileno()}))
-               input_pid = mypids[-1]
-               os.close(master_fd)
-               null_file.close()
-               fd_pipes[0] = slave_fd
+               fd_pipes[0] = fd_pipes_orig[0]
                fd_pipes[1] = slave_fd
                fd_pipes[2] = slave_fd
                keywords["fd_pipes"] = fd_pipes
 
        features = mysettings.features
-       restrict = mysettings.get("PORTAGE_RESTRICT","").split()
-       droppriv=(droppriv and "userpriv" in features and not \
-               ("nouserpriv" in restrict or "userpriv" in restrict))
+       # TODO: Enable fakeroot to be used together with droppriv.  The
+       # fake ownership/permissions will have to be converted to real
+       # permissions in the merge phase.
+       fakeroot = fakeroot and uid != 0 and portage.process.fakeroot_capable
        if droppriv and not uid and portage_gid and portage_uid:
                keywords.update({"uid":portage_uid,"gid":portage_gid,
                        "groups":userpriv_groups,"umask":002})
@@ -2466,6 +2427,10 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, **keyw
        if free or "SANDBOX_ACTIVE" in os.environ:
                keywords["opt_name"] += " bash"
                spawn_func = portage.process.spawn_bash
+       elif fakeroot:
+               keywords["opt_name"] += " fakeroot"
+               keywords["fakeroot_state"] = os.path.join(mysettings["T"], "fakeroot.state")
+               spawn_func = portage.process.spawn_fakeroot
        else:
                keywords["opt_name"] += " sandbox"
                spawn_func = portage.process.spawn_sandbox
@@ -2489,26 +2454,48 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, **keyw
        if returnpid:
                return mypids
 
-       if output_pid:
-               # tee will exit when the other end of the pseudo-terminal is closed.
-               os.waitpid(output_pid, 0)
-               portage.process.spawned_pids.remove(output_pid)
-       if input_pid:
-               # cat is blocking on stdin, so it must be killed.
-               import signal
-               try:
-                       os.kill(input_pid, signal.SIGTERM)
-               except OSError:
-                       pass # it died by itself
-               os.waitpid(input_pid, 0)
-               portage.process.spawned_pids.remove(input_pid)
+       if logfile:
+               log_file = open(logfile, 'a')
+               stdout_file = os.fdopen(os.dup(fd_pipes_orig[1]), 'w')
+               master_file = os.fdopen(master_fd, 'w+')
+               iwtd = [master_file]
+               owtd = []
+               ewtd = []
+               import array, fcntl, select
+               fd_flags = {}
+               for f in iwtd:
+                       fd_flags[f] = fcntl.fcntl(f.fileno(), fcntl.F_GETFL)
+               buffsize = 65536
+               eof = False
+               while not eof:
+                       events = select.select(iwtd, owtd, ewtd)
+                       for f in events[0]:
+                               # Use non-blocking mode to prevent read
+                               # calls from blocking indefinitely.
+                               fcntl.fcntl(f.fileno(), fcntl.F_SETFL,
+                                       fd_flags[f] | os.O_NONBLOCK)
+                               buf = array.array('B')
+                               try:
+                                       buf.fromfile(f, buffsize)
+                               except EOFError:
+                                       pass
+                               fcntl.fcntl(f.fileno(), fcntl.F_SETFL, fd_flags[f])
+                               if not buf:
+                                       eof = True
+                                       break
+                               # Use blocking mode for writes since we'd rather block than
+                               # trigger a EWOULDBLOCK error.
+                               if f is master_file:
+                                       buf.tofile(stdout_file)
+                                       stdout_file.flush()
+                                       buf.tofile(log_file)
+                                       log_file.flush()
+               log_file.close()
+               stdout_file.close()
+               master_file.close()
        pid = mypids[-1]
-       try:
-               retval = os.waitpid(pid, 0)[1]
-               portage.process.spawned_pids.remove(pid)
-       finally:
-               if stdin_termios:
-                       termios.tcsetattr(stdin_fd, termios.TCSAFLUSH, stdin_termios)
+       retval = os.waitpid(pid, 0)[1]
+       portage.process.spawned_pids.remove(pid)
        if retval != os.EX_OK:
                if retval & 0xff:
                        return (retval & 0xff) << 8
@@ -3768,7 +3755,7 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
                                pr, pw = os.pipe()
                                fd_pipes = {0:0, 1:1, 2:2, 9:pw}
                                mypids = spawn(EBUILD_SH_BINARY + " depend", mysettings,
-                                       fd_pipes=fd_pipes, returnpid=True)
+                                       fd_pipes=fd_pipes, returnpid=True, droppriv=1)
                                os.close(pw) # belongs exclusively to the child process now
                                maxbytes = 1024
                                mybytes = []
@@ -3796,7 +3783,7 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
                                mysettings["dbkey"] = \
                                        os.path.join(mysettings.depcachedir, "aux_db_key_temp")
 
-                       return spawn(EBUILD_SH_BINARY + " depend", mysettings)
+                       return spawn(EBUILD_SH_BINARY + " depend", mysettings, droppriv=1)
 
                # Validate dependency metadata here to ensure that ebuilds with invalid
                # data are never installed (even via the ebuild command).
@@ -4032,19 +4019,25 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
 
                sesandbox = mysettings.selinux_enabled() and \
                        "sesandbox" in mysettings.features
+
+               droppriv = "userpriv" in mysettings.features and \
+                       "userpriv" not in restrict
+
+               fakeroot = "fakeroot" in mysettings.features
+
                ebuild_sh = EBUILD_SH_BINARY + " %s"
                misc_sh = MISC_SH_BINARY + " dyn_%s"
 
                # args are for the to spawn function
                actionmap = {
-"depend": {"cmd":ebuild_sh, "args":{"droppriv":1, "free":0,         "sesandbox":0}},
-"setup":  {"cmd":ebuild_sh, "args":{"droppriv":0, "free":1,         "sesandbox":0}},
-"unpack": {"cmd":ebuild_sh, "args":{"droppriv":1, "free":0,         "sesandbox":sesandbox}},
-"compile":{"cmd":ebuild_sh, "args":{"droppriv":1, "free":nosandbox, "sesandbox":sesandbox}},
-"test":   {"cmd":ebuild_sh, "args":{"droppriv":1, "free":nosandbox, "sesandbox":sesandbox}},
-"install":{"cmd":ebuild_sh, "args":{"droppriv":0, "free":0,         "sesandbox":sesandbox}},
-"rpm":    {"cmd":misc_sh,   "args":{"droppriv":0, "free":0,         "sesandbox":0}},
-"package":{"cmd":misc_sh,   "args":{"droppriv":0, "free":0,         "sesandbox":0}},
+"depend": {"cmd":ebuild_sh, "args":{"droppriv":1,        "free":0,         "sesandbox":0,         "fakeroot":0}},
+"setup":  {"cmd":ebuild_sh, "args":{"droppriv":0,        "free":1,         "sesandbox":0,         "fakeroot":0}},
+"unpack": {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":0,         "sesandbox":sesandbox, "fakeroot":0}},
+"compile":{"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":nosandbox, "sesandbox":sesandbox, "fakeroot":0}},
+"test":   {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":nosandbox, "sesandbox":sesandbox, "fakeroot":0}},
+"install":{"cmd":ebuild_sh, "args":{"droppriv":0,        "free":0,         "sesandbox":sesandbox, "fakeroot":fakeroot}},
+"rpm":    {"cmd":misc_sh,   "args":{"droppriv":0,        "free":0,         "sesandbox":0,         "fakeroot":fakeroot}},
+"package":{"cmd":misc_sh,   "args":{"droppriv":0,        "free":0,         "sesandbox":0,         "fakeroot":fakeroot}},
                }
 
                # merge the deps in so we have again a 'full' actionmap
index 34eff92a7e583fc42ff4150426d2d184576403a5..00d5b21121129e63e416b0bb886727840de23901 100644 (file)
@@ -130,17 +130,8 @@ class portdbapi(dbapi):
                modemask =    02
 
                try:
-                       for mydir in (self.depcachedir,):
-                               if ensure_dirs(mydir, gid=portage_gid, mode=dirmode, mask=modemask):
-                                       writemsg("Adjusting permissions recursively: '%s'\n" % mydir,
-                                               noiselevel=-1)
-                                       def onerror(e):
-                                               raise # bail out on the first error that occurs during recursion
-                                       if not apply_recursive_permissions(mydir,
-                                               gid=portage_gid, dirmode=dirmode, dirmask=modemask,
-                                               filemode=filemode, filemask=modemask, onerror=onerror):
-                                               raise OperationNotPermitted(
-                                                       "Failed to apply recursive permissions for the portage group.")
+                       ensure_dirs(self.depcachedir, gid=portage_gid,
+                               mode=dirmode, mask=modemask)
                except PortageException, e:
                        pass
 
index fad38770e2fd7f8d57920ca3f854c2da526e81ee..fcec7588c3246926a16e7dc58b016133a3d5a1c1 100644 (file)
@@ -10,7 +10,7 @@ import signal
 import sys
 
 from portage.util import dump_traceback
-from portage.const import BASH_BINARY, SANDBOX_BINARY
+from portage.const import BASH_BINARY, SANDBOX_BINARY, FAKEROOT_BINARY
 from portage.exception import CommandNotFound
 
 try:
@@ -29,6 +29,9 @@ else:
 sandbox_capable = (os.path.isfile(SANDBOX_BINARY) and
                    os.access(SANDBOX_BINARY, os.X_OK))
 
+fakeroot_capable = (os.path.isfile(FAKEROOT_BINARY) and
+                    os.access(FAKEROOT_BINARY, os.X_OK))
+
 def spawn_bash(mycommand, debug=False, opt_name=None, **keywords):
        """
        Spawns a bash shell running a specific commands
@@ -62,6 +65,22 @@ def spawn_sandbox(mycommand, opt_name=None, **keywords):
        args.append(mycommand)
        return spawn(args, opt_name=opt_name, **keywords)
 
+def spawn_fakeroot(mycommand, fakeroot_state=None, opt_name=None, **keywords):
+       args=[FAKEROOT_BINARY]
+       if not opt_name:
+               opt_name = os.path.basename(mycommand.split()[0])
+       if fakeroot_state:
+               open(fakeroot_state, "a").close()
+               args.append("-s")
+               args.append(fakeroot_state)
+               args.append("-i")
+               args.append(fakeroot_state)
+       args.append("--")
+       args.append(BASH_BINARY)
+       args.append("-c")
+       args.append(mycommand)
+       return spawn(args, opt_name=opt_name, **keywords)
+
 _exithandlers = []
 def atexit_register(func, *args, **kargs):
        """Wrapper around atexit.register that is needed in order to track
@@ -113,16 +132,6 @@ def cleanup():
 
 atexit_register(cleanup)
 
-# Make sure the original terminal attributes are reverted at exit.
-if hasattr(sys.stdin, "isatty") and sys.stdin.isatty():
-       import termios
-       _stdin_termios = termios.tcgetattr(sys.stdin.fileno())
-       def _reset_stdin_termios(stdin_termios):
-               import termios
-               termios.tcsetattr(sys.stdin.fileno(), termios.TCSAFLUSH, stdin_termios)
-       atexit_register(_reset_stdin_termios, _stdin_termios)
-       del termios, _stdin_termios, _reset_stdin_termios
-
 def spawn(mycommand, env={}, opt_name=None, fd_pipes=None, returnpid=False,
           uid=None, gid=None, groups=None, umask=None, logfile=None,
           path_lookup=True, pre_exec=None):