Index: trunk/pym/portage/__init__.py =================================================================== --- trunk/pym/portage/__init__.py (revision 7293) +++ trunk/pym/portage/__init__.py (working copy) @@ -2326,7 +2326,7 @@ # 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: @@ -2354,6 +2354,8 @@ @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 @@ -2446,6 +2448,7 @@ restrict = mysettings.get("PORTAGE_RESTRICT","").split() droppriv=(droppriv and "userpriv" in features and not \ ("nouserpriv" in restrict or "userpriv" in restrict)) + fakeroot=(fakeroot and uid and "fakeroot" in features) if droppriv and not uid and portage_gid and portage_uid: keywords.update({"uid":portage_uid,"gid":portage_gid, "groups":userpriv_groups,"umask":002}) @@ -2457,6 +2460,10 @@ 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 @@ -3996,14 +4003,14 @@ # 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":1, "free":0, "sesandbox":sesandbox, "fakeroot":0}}, +"compile":{"cmd":ebuild_sh, "args":{"droppriv":1, "free":nosandbox, "sesandbox":sesandbox, "fakeroot":0}}, +"test": {"cmd":ebuild_sh, "args":{"droppriv":1, "free":nosandbox, "sesandbox":sesandbox, "fakeroot":0}}, +"install":{"cmd":ebuild_sh, "args":{"droppriv":0, "free":0, "sesandbox":sesandbox, "fakeroot":1}}, +"rpm": {"cmd":misc_sh, "args":{"droppriv":0, "free":0, "sesandbox":0, "fakeroot":1}}, +"package":{"cmd":misc_sh, "args":{"droppriv":0, "free":0, "sesandbox":0, "fakeroot":1}}, } # merge the deps in so we have again a 'full' actionmap Index: trunk/pym/portage/const.py =================================================================== --- trunk/pym/portage/const.py (revision 7293) +++ trunk/pym/portage/const.py (working copy) @@ -30,6 +30,7 @@ EBUILD_SH_BINARY = PORTAGE_BIN_PATH+"/ebuild.sh" MISC_SH_BINARY = PORTAGE_BIN_PATH + "/misc-functions.sh" SANDBOX_BINARY = "/usr/bin/sandbox" +FAKEROOT_BINARY = "/usr/bin/fakeroot" BASH_BINARY = "/bin/bash" MOVE_BINARY = "/bin/mv" PRELINK_BINARY = "/usr/sbin/prelink" Index: trunk/pym/portage/process.py =================================================================== --- trunk/pym/portage/process.py (revision 7293) +++ trunk/pym/portage/process.py (working copy) @@ -8,7 +8,7 @@ import portage.data 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: @@ -27,6 +27,9 @@ 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 @@ -60,6 +63,24 @@ args.append(mycommand) return spawn(args, opt_name=opt_name, **keywords) +def spawn_fakeroot(mycommand, fakeroot_state=None, opt_name=None, **keywords): + if not fakeroot_capable: + return spawn_bash(mycommand, opt_name=opt_name, **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 Index: trunk/bin/ebuild.sh =================================================================== --- trunk/bin/ebuild.sh (revision 7293) +++ trunk/bin/ebuild.sh (working copy) @@ -1648,8 +1648,8 @@ 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:portage "${T}/environment" &>/dev/null chmod g+w "${T}/environment" &>/dev/null