diff options
author | Zac Medico <zmedico@gentoo.org> | 2007-07-23 23:33:08 +0000 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2007-07-23 23:33:08 +0000 |
commit | c2b6ed727403b5066190ae241dd2d5457bd6d51b (patch) | |
tree | 4b22d492bbf7d71b33638fcc7e4c8f17373e613a | |
parent | 9da048e7cd73b341a69254efe4816a6df2a6ab02 (diff) | |
download | portage-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-x | bin/ebuild.sh | 4 | ||||
-rw-r--r-- | man/make.conf.5 | 4 | ||||
-rw-r--r-- | pym/portage/__init__.py | 31 | ||||
-rw-r--r-- | pym/portage/const.py | 1 | ||||
-rw-r--r-- | pym/portage/dbapi/porttree.py | 13 | ||||
-rw-r--r-- | pym/portage/process.py | 21 |
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 |