summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2007-07-23 23:33:08 +0000
committerZac Medico <zmedico@gentoo.org>2007-07-23 23:33:08 +0000
commitc2b6ed727403b5066190ae241dd2d5457bd6d51b (patch)
tree4b22d492bbf7d71b33638fcc7e4c8f17373e613a
parent9da048e7cd73b341a69254efe4816a6df2a6ab02 (diff)
downloadportage-c2b6ed727403b5066190ae241dd2d5457bd6d51b.tar.gz
portage-c2b6ed727403b5066190ae241dd2d5457bd6d51b.tar.bz2
portage-c2b6ed727403b5066190ae241dd2d5457bd6d51b.zip
Add FEATURES=fakeroot support which causes install and package phases to run inside fakeroot when a non-root user runs the ebuild command. Thanks to swegener for the initial patch.
svn path=/main/trunk/; revision=7379
-rwxr-xr-xbin/ebuild.sh4
-rw-r--r--man/make.conf.54
-rw-r--r--pym/portage/__init__.py31
-rw-r--r--pym/portage/const.py1
-rw-r--r--pym/portage/dbapi/porttree.py13
-rw-r--r--pym/portage/process.py21
6 files changed, 50 insertions, 24 deletions
diff --git a/bin/ebuild.sh b/bin/ebuild.sh
index 5f271524b..72b449927 100755
--- a/bin/ebuild.sh
+++ b/bin/ebuild.sh
@@ -1648,8 +1648,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:portage "${T}/environment" &>/dev/null
chmod g+w "${T}/environment" &>/dev/null
diff --git a/man/make.conf.5 b/man/make.conf.5
index 4ae3a2f94..da6df14dc 100644
--- a/man/make.conf.5
+++ b/man/make.conf.5
@@ -169,6 +169,10 @@ strangely configured Samba server (oplocks off, NFS re\-export). A tool
/usr/lib/portage/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
diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py
index a151ad064..3fe82f63e 100644
--- a/pym/portage/__init__.py
+++ b/pym/portage/__init__.py
@@ -2326,7 +2326,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:
@@ -2354,6 +2354,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
@@ -2443,7 +2445,10 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, **keyw
keywords["fd_pipes"] = fd_pipes
features = mysettings.features
- restrict = mysettings.get("PORTAGE_RESTRICT","").split()
+ # 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})
@@ -2455,6 +2460,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
@@ -4022,19 +4031,21 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
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":droppriv, "free":0, "sesandbox":sesandbox}},
-"compile":{"cmd":ebuild_sh, "args":{"droppriv":droppriv, "free":nosandbox, "sesandbox":sesandbox}},
-"test": {"cmd":ebuild_sh, "args":{"droppriv":droppriv, "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
diff --git a/pym/portage/const.py b/pym/portage/const.py
index 28e6f36ff..d8bd604d1 100644
--- a/pym/portage/const.py
+++ b/pym/portage/const.py
@@ -30,6 +30,7 @@ LOCALE_DATA_PATH = PORTAGE_BASE_PATH+"/locale"
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"
diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py
index 34eff92a7..00d5b2112 100644
--- a/pym/portage/dbapi/porttree.py
+++ b/pym/portage/dbapi/porttree.py
@@ -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
diff --git a/pym/portage/process.py b/pym/portage/process.py
index fad38770e..8b9ab30e2 100644
--- a/pym/portage/process.py
+++ b/pym/portage/process.py
@@ -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