aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml14
-rw-r--r--AUTHORS8
-rw-r--r--Makefile.am8
-rw-r--r--README9
-rw-r--r--acinclude.m483
-rwxr-xr-xautogen.sh19
-rw-r--r--bin/Makefile.in76
-rwxr-xr-xbin/archive-conf2
-rw-r--r--bin/bashrc-functions.sh2
-rwxr-xr-xbin/binhost-snapshot2
-rwxr-xr-xbin/check-implicit-pointer-usage.py2
-rwxr-xr-xbin/chmod-lite4
-rwxr-xr-xbin/chmod-lite.py2
-rwxr-xr-xbin/chpathtool.py2
-rwxr-xr-xbin/clean_locks2
-rwxr-xr-xbin/dispatch-conf2
-rwxr-xr-xbin/dohtml.py2
-rw-r--r--bin/eapi.sh2
-rwxr-xr-xbin/ebuild2
-rwxr-xr-xbin/ebuild-helpers/bsd/sed9
-rwxr-xr-xbin/ebuild-helpers/die2
-rwxr-xr-xbin/ebuild-helpers/dobin2
-rwxr-xr-xbin/ebuild-helpers/doconfd2
-rwxr-xr-xbin/ebuild-helpers/dodir2
-rwxr-xr-xbin/ebuild-helpers/dodoc2
-rwxr-xr-xbin/ebuild-helpers/doenvd2
-rwxr-xr-xbin/ebuild-helpers/doexe2
-rwxr-xr-xbin/ebuild-helpers/dohard2
-rwxr-xr-xbin/ebuild-helpers/doheader2
-rwxr-xr-xbin/ebuild-helpers/dohtml4
-rwxr-xr-xbin/ebuild-helpers/doinfo2
-rwxr-xr-xbin/ebuild-helpers/doinitd2
-rwxr-xr-xbin/ebuild-helpers/doins11
-rwxr-xr-xbin/ebuild-helpers/dolib2
-rwxr-xr-xbin/ebuild-helpers/dolib.a2
-rwxr-xr-xbin/ebuild-helpers/dolib.so2
-rwxr-xr-xbin/ebuild-helpers/doman2
-rwxr-xr-xbin/ebuild-helpers/domo2
-rwxr-xr-xbin/ebuild-helpers/dosbin2
-rwxr-xr-xbin/ebuild-helpers/dosed2
-rwxr-xr-xbin/ebuild-helpers/dosym2
-rwxr-xr-xbin/ebuild-helpers/elog2
-rwxr-xr-xbin/ebuild-helpers/emake4
-rwxr-xr-xbin/ebuild-helpers/fowners2
-rwxr-xr-xbin/ebuild-helpers/fperms2
-rwxr-xr-xbin/ebuild-helpers/keepdir2
-rwxr-xr-xbin/ebuild-helpers/newins2
-rwxr-xr-xbin/ebuild-helpers/portageq4
-rwxr-xr-xbin/ebuild-helpers/prepall2
-rwxr-xr-xbin/ebuild-helpers/prepalldocs2
-rwxr-xr-xbin/ebuild-helpers/prepallinfo2
-rwxr-xr-xbin/ebuild-helpers/prepallman2
-rwxr-xr-xbin/ebuild-helpers/prepallstrip2
-rwxr-xr-xbin/ebuild-helpers/prepinfo2
-rwxr-xr-xbin/ebuild-helpers/prepman2
-rwxr-xr-xbin/ebuild-helpers/prepstrip2
-rwxr-xr-xbin/ebuild-helpers/unprivileged/chown2
-rwxr-xr-xbin/ebuild-helpers/xattr/install2
-rwxr-xr-xbin/ebuild-ipc4
-rwxr-xr-xbin/ebuild-ipc.py2
-rwxr-xr-xbin/ebuild.sh4
-rwxr-xr-xbin/egencache2
-rwxr-xr-xbin/emaint2
-rwxr-xr-xbin/emerge2
-rwxr-xr-xbin/emerge-webrsync14
-rwxr-xr-xbin/emirrordist2
-rwxr-xr-xbin/env-update2
-rwxr-xr-xbin/etc-update4
-rwxr-xr-xbin/filter-bash-environment.py2
-rwxr-xr-xbin/fixpackages2
-rwxr-xr-xbin/glsa-check2
-rw-r--r--bin/helper-functions.sh2
-rw-r--r--bin/install-qa-check.d/05prefix74
-rw-r--r--bin/install-qa-check.d/80libraries13
-rw-r--r--bin/install-qa-check.d/80multilib-strict2
-rw-r--r--bin/install-qa-check.d/90gcc-warnings2
-rw-r--r--bin/install-qa-check.d/90world-writable8
-rwxr-xr-xbin/install.py2
-rw-r--r--bin/isolated-functions.sh28
-rwxr-xr-xbin/lock-helper.py2
-rwxr-xr-xbin/misc-functions.sh687
-rw-r--r--bin/phase-functions.sh9
-rw-r--r--bin/phase-helpers.sh18
-rwxr-xr-xbin/portageq6
-rwxr-xr-xbin/quickpkg2
-rwxr-xr-xbin/readpecoff108
-rwxr-xr-xbin/regenworld2
-rwxr-xr-x[-rw-r--r--]bin/save-ebuild-env.sh16
-rwxr-xr-xbin/xattr-helper.py2
-rwxr-xr-xbin/xpak-helper.py2
-rw-r--r--cnf/Makefile.in42
-rw-r--r--cnf/make.conf.example18
-rw-r--r--cnf/make.globals49
-rw-r--r--cnf/repos.conf8
-rw-r--r--configure.ac135
-rw-r--r--lib/Makefile.in41
-rw-r--r--lib/_emerge/Package.py2
-rw-r--r--lib/_emerge/actions.py40
-rw-r--r--lib/_emerge/depgraph.py10
-rw-r--r--lib/_emerge/emergelog.py3
-rw-r--r--lib/_emerge/getloadavg.py15
-rw-r--r--lib/portage/__init__.py3
-rw-r--r--lib/portage/const.py33
-rw-r--r--lib/portage/const_autotool.py21
-rw-r--r--lib/portage/data.py63
-rw-r--r--lib/portage/dbapi/bintree.py9
-rw-r--r--lib/portage/dbapi/vartree.py28
-rw-r--r--lib/portage/getbinpkg.py5
-rw-r--r--lib/portage/package/ebuild/_config/special_env_vars.py9
-rw-r--r--lib/portage/package/ebuild/config.py72
-rw-r--r--lib/portage/package/ebuild/doebuild.py96
-rw-r--r--lib/portage/package/ebuild/fetch.py3
-rw-r--r--lib/portage/process.py17
-rw-r--r--lib/portage/tests/lazyimport/test_lazy_import_portage_baseline.py1
-rw-r--r--lib/portage/tests/resolver/ResolverPlayground.py1
-rwxr-xr-xlib/portage/tests/runTests.py12
-rw-r--r--lib/portage/util/__init__.py21
-rw-r--r--lib/portage/util/_dyn_libs/LinkageMapMachO.py773
-rw-r--r--lib/portage/util/_dyn_libs/LinkageMapPeCoff.py286
-rw-r--r--lib/portage/util/_dyn_libs/LinkageMapXCoff.py312
-rw-r--r--lib/portage/util/_info_files.py7
-rw-r--r--lib/portage/util/_pty.py8
-rw-r--r--lib/portage/util/env_update.py6
-rw-r--r--lib/portage/versions.py42
-rw-r--r--man/Makefile.am17
-rw-r--r--man/ebuild.56
-rw-r--r--man/emerge.17
-rw-r--r--man/make.conf.56
-rwxr-xr-xmisc/emerge-delta-webrsync2
-rwxr-xr-xruntests2
-rw-r--r--subst-install.in74
-rwxr-xr-xtabcheck.py3
-rwxr-xr-xtarball.sh55
-rwxr-xr-xtravis.sh31
134 files changed, 3507 insertions, 259 deletions
diff --git a/.travis.yml b/.travis.yml
index 2132c8c87..6d3afa4ce 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,6 +17,20 @@ install:
script:
- printf "[build_ext]\nportage-ext-modules=true" >> setup.cfg
+ - find . -type f -exec
+ sed -e "s|@PORTAGE_EPREFIX@||"
+ -e "s|@PORTAGE_BASE@|${PWD}|"
+ -e "s|@PORTAGE_MV@|$(type -P mv)|"
+ -e "s|@PORTAGE_BASH@|$(type -P bash)|"
+ -e "s|@PREFIX_PORTAGE_PYTHON@|$(type -P python)|"
+ -e "s|@EXTRA_PATH@|/usr/sbin:/sbin|"
+ -e "s|@portagegroup@|$(id -gn)|"
+ -e "s|@portageuser@|$(id -un)|"
+ -e "s|@rootuser@|$(id -un)|"
+ -e "s|@rootuid@|$(id -u)|"
+ -e "s|@rootgid@|$(id -g)|"
+ -e "s|@sysconfdir@|/etc|"
+ -i '{}' +
- ./setup.py test
- ./setup.py install --root=/tmp/install-root
- if [[ ${TRAVIS_PYTHON_VERSION/-dev/} == ?.? ]]; then
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 000000000..62b0edcbd
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,8 @@
+In addition to the the long list of regular portage contributors, these
+folks (in no particular order) have put their hard work into this.
+
+Kito Dietrich <kito at ???>
+Emanuele Giaquinta <emanuele.giaquinta at gmail.com>
+Fabian Groffen <grobian at gentoo.org>
+Brian Harring <ferringb at gmail.com>
+Michael Haubenwallner <haubi at gentoo.org>
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 000000000..9bcfa00e7
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,8 @@
+SHELL = @PORTAGE_BASH@
+
+SUBDIRS = man bin lib cnf
+
+AUTOMAKE_OPTIONS = dist-bzip2 no-dist-gzip
+
+MAINTAINERCLEANFILES = \
+ Makefile.in config.guess config.sub configure ltmain.sh aclocal.m4
diff --git a/README b/README
index cae987242..4ab10c6b5 100644
--- a/README
+++ b/README
@@ -1,3 +1,12 @@
+This is the prefix branch of portage, a branch that deals with portage
+setup as packagemanager for a given offset in the filesystem running
+with user privileges.
+
+If you are not looking for something Gentoo Prefix like, then this
+is not the right place.
+
+
+=======
About Portage
=============
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 000000000..1d9ccf55f
--- /dev/null
+++ b/acinclude.m4
@@ -0,0 +1,83 @@
+dnl acinclude.m4 generated automatically by ac-archive's acinclude 0.5.63
+
+dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+dnl ______ ______
+
+dnl GENTOO_PATH_PYTHON([minimum-version], [path])
+dnl author: Fabian Groffen <grobian a gentoo.org>
+AC_DEFUN([GENTOO_PATH_PYTHON],
+[
+ AC_PATH_PROG([PREFIX_PORTAGE_PYTHON], [python], no, $2)
+
+ dnl is is there at all?
+ if test "$PREFIX_PORTAGE_PYTHON" = "no" ; then
+ AC_MSG_ERROR([no python found in your path])
+ fi
+
+ dnl is it the version we want?
+ ver=`$PREFIX_PORTAGE_PYTHON -c 'import sys; print(sys.version.split(" ")[[0]])'`
+ AC_MSG_CHECKING([whether $PREFIX_PORTAGE_PYTHON $ver >= $1])
+ cmp=`$PREFIX_PORTAGE_PYTHON -c 'import sys; print(sys.version.split(" ")[[0]] >= "$1")'`
+ if test "$cmp" = "True" ; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_ERROR([need at least version $1 of python])
+ fi
+])
+
+dnl GENTOO_PATH_XCU_ID([path])
+dnl author: Fabian Groffen <grobian a gentoo.org>
+dnl based on the original work by
+dnl Michael Haubenwallner <mhaubi at users dot sourceforge dot net>
+AC_DEFUN([GENTOO_PATH_XCU_ID],
+[
+ AC_PATH_PROG([XCU_ID], [id], no, $1)
+
+ dnl does it support all the bells and whistles we need?
+ AC_MSG_CHECKING([whether $XCU_ID is good enough])
+ for a in '' '-u' '-g' ; do
+ if ! "$XCU_ID" $a >/dev/null 2>&1 ; then
+ XCU_ID=no
+ break
+ fi
+ done
+ if test "$XCU_ID" != "no" ; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_ERROR([$XCU_ID doesn't understand $a])
+ fi
+])dnl
+
+dnl GENTOO_PATH_GNUPROG([variable], [prog-to-check-for], [path])
+dnl author: Fabian Groffen <grobian a gentoo.org>
+AC_DEFUN([GENTOO_PATH_GNUPROG],
+[
+ AC_PATH_PROG([$1], [$2], no, $3)
+
+ dnl is is there at all?
+ tool="`eval echo \$$1`"
+ if test "$tool" = "no" ; then
+ AC_MSG_ERROR([$1 was not found in your path])
+ fi
+
+ dnl is it a GNU version?
+ AC_MSG_CHECKING([whether $tool is GNU $2])
+ ver=`$tool --version 2>/dev/null | head -n 1`
+ case $ver in
+ *GNU*)
+ AC_MSG_RESULT([yes])
+ ;;
+ *)
+ AC_MSG_ERROR([no])
+ ;;
+ esac
+])
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 000000000..ec510e01b
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env sh
+
+die() {
+ echo "!!! $*" > /dev/stderr
+ exit -1
+}
+
+#autoheader || { echo "failed autoheader"; exit 1; };
+aclocal || die "failed aclocal"
+[ "`type -t glibtoolize`" = "file" ] && alias libtoolize=glibtoolize
+libtoolize --automake -c -f || die "failed libtoolize"
+autoconf || die "failed autoconf"
+touch ChangeLog
+automake -a -c || die "failed automake"
+
+if [ -x ./test.sh ] ; then
+ exec ./test.sh "$@"
+fi
+echo "finished"
diff --git a/bin/Makefile.in b/bin/Makefile.in
new file mode 100644
index 000000000..afff11dfb
--- /dev/null
+++ b/bin/Makefile.in
@@ -0,0 +1,76 @@
+SHELL = @PORTAGE_BASH@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+sysconfdir = @sysconfdir@
+libdir = @libdir@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+
+portageuser = @portageuser@
+portagegroup = @portagegroup@
+
+PORTAGE_BIN = @PORTAGE_BASE@/bin
+LN_S = @LN_S@
+INSTALL = @INSTALL@
+INSTALL_subst = $(top_builddir)/subst-install
+
+usr_binprogs = \
+ ebuild \
+ egencache \
+ emerge \
+ emerge-webrsync \
+ emirrordist \
+ portageq \
+ quickpkg
+
+usr_sbinprogs = \
+ archive-conf \
+ dispatch-conf \
+ emaint \
+ env-update \
+ etc-update \
+ fixpackages \
+ readpecoff \
+ regenworld
+
+all:
+
+install:
+ $(INSTALL) -d -m 755 -o "$(portageuser)" -g "$(portagegroup)" $(DESTDIR)$(PORTAGE_BIN)
+ ( cd "$(srcdir)" && find . -type d ) | while read f ; do \
+ files=( ) ; \
+ shopt -s nullglob ; \
+ for t in "$(srcdir)/$${f}"/* ; do \
+ [[ -d $${t} ]] && continue ; \
+ [[ $${t} == */Makefile* ]] && continue ; \
+ files=( "$${files[@]}" "$${t}" ) ; \
+ done ; \
+ $(INSTALL) -d -m 755 \
+ -o "$(portageuser)" -g "$(portagegroup)" \
+ "$(DESTDIR)$(PORTAGE_BIN)/$${f}" && \
+ [[ $${files[0]} ]] || continue ; \
+ $(INSTALL_subst) -m 755 \
+ -o "$(portageuser)" -g "$(portagegroup)" \
+ -t "$(DESTDIR)$(PORTAGE_BIN)/$${f}" \
+ "$${files[@]}" ; \
+ done
+ $(INSTALL) -d -m 755 -o "$(portageuser)" -g "$(portagegroup)" $(DESTDIR)$(prefix)/bin
+ cd $(DESTDIR)$(prefix)/bin \
+ ; for p in $(usr_binprogs) \
+ ; do test -f $(DESTDIR)$(PORTAGE_BIN)/$${p} \
+ || { echo "$(DESTDIR)$(PORTAGE_BIN)/$${p} does not exist" ; exit 1 ; } \
+ ; rm -f $(DESTDIR)$(prefix)/bin/$${p} \
+ ; $(LN_S) ../lib/portage/bin/$${p} $${p} || exit 1 \
+ ; done
+ $(INSTALL) -d -m 755 -o "$(portageuser)" -g "$(portagegroup)" $(DESTDIR)$(prefix)/sbin
+ cd $(DESTDIR)$(prefix)/sbin \
+ ; for p in $(usr_sbinprogs) \
+ ; do test -f $(DESTDIR)$(PORTAGE_BIN)/$${p} \
+ || { echo "$(DESTDIR)$(PORTAGE_BIN)/$${p} does not exist" ; exit 1 ; } \
+ ; rm -f $(DESTDIR)$(prefix)/sbin/$${p} \
+ ; $(LN_S) ../lib/portage/bin/$${p} $${p} || exit 1 \
+ ; done
+
+.PHONY: all install
diff --git a/bin/archive-conf b/bin/archive-conf
index 8341ffe73..6271b833c 100755
--- a/bin/archive-conf
+++ b/bin/archive-conf
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/bashrc-functions.sh b/bin/bashrc-functions.sh
index cc025467f..f01f5c5d0 100644
--- a/bin/bashrc-functions.sh
+++ b/bin/bashrc-functions.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/binhost-snapshot b/bin/binhost-snapshot
index d677e7568..41d556831 100755
--- a/bin/binhost-snapshot
+++ b/bin/binhost-snapshot
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 2010-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/check-implicit-pointer-usage.py b/bin/check-implicit-pointer-usage.py
index a49db8107..7921d005d 100755
--- a/bin/check-implicit-pointer-usage.py
+++ b/bin/check-implicit-pointer-usage.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Ripped from HP and updated from Debian
# Update by Gentoo to support unicode output
diff --git a/bin/chmod-lite b/bin/chmod-lite
index ffa8d4d23..8c62e2de7 100755
--- a/bin/chmod-lite
+++ b/bin/chmod-lite
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
@@ -7,4 +7,4 @@ export __PORTAGE_HELPER_CWD=${PWD}
# Use safe cwd, avoiding unsafe import for bug #469338.
cd "${PORTAGE_PYM_PATH}" || exit 1
PYTHONPATH=${PORTAGE_PYTHONPATH:-${PORTAGE_PYM_PATH}} \
- exec "${PORTAGE_PYTHON:-/usr/bin/python}" "$PORTAGE_BIN_PATH/chmod-lite.py" "$@"
+ exec "${PORTAGE_PYTHON:-@PREFIX_PORTAGE_PYTHON@}" "$PORTAGE_BIN_PATH/chmod-lite.py" "$@"
diff --git a/bin/chmod-lite.py b/bin/chmod-lite.py
index 177be7eab..b9a4fc9a2 100755
--- a/bin/chmod-lite.py
+++ b/bin/chmod-lite.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/chpathtool.py b/bin/chpathtool.py
index fbd18b987..b9483b841 100755
--- a/bin/chpathtool.py
+++ b/bin/chpathtool.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 2011-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/clean_locks b/bin/clean_locks
index 94ba4c606..a35b9f73a 100755
--- a/bin/clean_locks
+++ b/bin/clean_locks
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/dispatch-conf b/bin/dispatch-conf
index 62ab3f6cc..c05215fc3 100755
--- a/bin/dispatch-conf
+++ b/bin/dispatch-conf
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 1999-2019 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/dohtml.py b/bin/dohtml.py
index dfcaa6026..f99cd9812 100755
--- a/bin/dohtml.py
+++ b/bin/dohtml.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/eapi.sh b/bin/eapi.sh
index 29dfb008c..26df37328 100644
--- a/bin/eapi.sh
+++ b/bin/eapi.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 2012-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild b/bin/ebuild
index 460aa0fd1..a57dd4941 100755
--- a/bin/ebuild
+++ b/bin/ebuild
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 1999-2019 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/bsd/sed b/bin/ebuild-helpers/bsd/sed
index 8bece09cd..fd8dc2183 100755
--- a/bin/ebuild-helpers/bsd/sed
+++ b/bin/ebuild-helpers/bsd/sed
@@ -1,10 +1,17 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 2007-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
scriptpath=${BASH_SOURCE[0]}
scriptname=${scriptpath##*/}
+# PREFIX LOCAL: warn about screwups early
+if [[ -n ${EPREFIX} ]] ; then
+ echo "When using Prefix, this BSD sed wrapper should not exist (in ${scriptpath})! This is a bug!" > /dev/stderr
+ exit 1
+fi
+# END PREFIX LOCAL
+
if [[ sed == ${scriptname} && -n ${ESED} ]]; then
exec ${ESED} "$@"
elif type -P g${scriptname} > /dev/null ; then
diff --git a/bin/ebuild-helpers/die b/bin/ebuild-helpers/die
index 5c6b1d2cb..00b67901f 100755
--- a/bin/ebuild-helpers/die
+++ b/bin/ebuild-helpers/die
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/dobin b/bin/ebuild-helpers/dobin
index 975067fb1..0f0518aba 100755
--- a/bin/ebuild-helpers/dobin
+++ b/bin/ebuild-helpers/dobin
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/doconfd b/bin/ebuild-helpers/doconfd
index 15ad980f3..e32c9d5c0 100755
--- a/bin/ebuild-helpers/doconfd
+++ b/bin/ebuild-helpers/doconfd
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/dodir b/bin/ebuild-helpers/dodir
index 9b376c73f..4d309e4b1 100755
--- a/bin/ebuild-helpers/dodir
+++ b/bin/ebuild-helpers/dodir
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/dodoc b/bin/ebuild-helpers/dodoc
index e83091045..9fdb6495a 100755
--- a/bin/ebuild-helpers/dodoc
+++ b/bin/ebuild-helpers/dodoc
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/doenvd b/bin/ebuild-helpers/doenvd
index f14b95104..4e8068659 100755
--- a/bin/ebuild-helpers/doenvd
+++ b/bin/ebuild-helpers/doenvd
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/doexe b/bin/ebuild-helpers/doexe
index 152c13bf6..5fa8f058d 100755
--- a/bin/ebuild-helpers/doexe
+++ b/bin/ebuild-helpers/doexe
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/dohard b/bin/ebuild-helpers/dohard
index 66e2604b0..1dd2eb582 100755
--- a/bin/ebuild-helpers/dohard
+++ b/bin/ebuild-helpers/dohard
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/doheader b/bin/ebuild-helpers/doheader
index aedc2322a..a87536c33 100755
--- a/bin/ebuild-helpers/doheader
+++ b/bin/ebuild-helpers/doheader
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/dohtml b/bin/ebuild-helpers/dohtml
index 49d6a6dfb..a60dbdab8 100755
--- a/bin/ebuild-helpers/dohtml
+++ b/bin/ebuild-helpers/dohtml
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 2009-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
@@ -17,7 +17,7 @@ fi
export __PORTAGE_HELPER_CWD=${PWD}
cd "${PORTAGE_PYM_PATH}" || die
PYTHONPATH=${PORTAGE_PYTHONPATH:-${PORTAGE_PYM_PATH}} \
- "${PORTAGE_PYTHON:-/usr/bin/python}" "$PORTAGE_BIN_PATH/dohtml.py" "$@"
+ "${PORTAGE_PYTHON:-@PREFIX_PORTAGE_PYTHON@}" "$PORTAGE_BIN_PATH/dohtml.py" "$@"
ret=$?
# Restore cwd for display by __helpers_die
diff --git a/bin/ebuild-helpers/doinfo b/bin/ebuild-helpers/doinfo
index 30a38e055..e261e9e74 100755
--- a/bin/ebuild-helpers/doinfo
+++ b/bin/ebuild-helpers/doinfo
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/doinitd b/bin/ebuild-helpers/doinitd
index a216d9827..883858320 100755
--- a/bin/ebuild-helpers/doinitd
+++ b/bin/ebuild-helpers/doinitd
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/doins b/bin/ebuild-helpers/doins
index 24fe48121..825a421af 100755
--- a/bin/ebuild-helpers/doins
+++ b/bin/ebuild-helpers/doins
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2019 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
@@ -50,6 +50,15 @@ if [[ ${_E_INSDESTTREE_#${ED}} != "${_E_INSDESTTREE_}" ]]; then
__helpers_die "${helper} used with \${D} or \${ED}"
exit 1
fi
+# PREFIX LOCAL: check for usage with EPREFIX
+if [[ ${INSDESTTREE#${EPREFIX}} != "${INSDESTTREE}" ]]; then
+ __vecho "-------------------------------------------------------" 1>&2
+ __vecho "You should not use \${EPREFIX} with helpers." 1>&2
+ __vecho " --> ${INSDESTTREE}" 1>&2
+ __vecho "-------------------------------------------------------" 1>&2
+ exit 1
+fi
+# END PREFIX LOCAL
if ___eapi_doins_and_newins_preserve_symlinks; then
DOINS_ARGS+=( --preserve_symlinks )
diff --git a/bin/ebuild-helpers/dolib b/bin/ebuild-helpers/dolib
index bd8eebca7..049088de7 100755
--- a/bin/ebuild-helpers/dolib
+++ b/bin/ebuild-helpers/dolib
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/dolib.a b/bin/ebuild-helpers/dolib.a
index 5ea126b5d..f45aed3e6 100755
--- a/bin/ebuild-helpers/dolib.a
+++ b/bin/ebuild-helpers/dolib.a
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/dolib.so b/bin/ebuild-helpers/dolib.so
index a3b579e5e..2272679c8 100755
--- a/bin/ebuild-helpers/dolib.so
+++ b/bin/ebuild-helpers/dolib.so
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/doman b/bin/ebuild-helpers/doman
index 9cfc89df0..bfd7356a0 100755
--- a/bin/ebuild-helpers/doman
+++ b/bin/ebuild-helpers/doman
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/domo b/bin/ebuild-helpers/domo
index 2e95eb751..fb1475470 100755
--- a/bin/ebuild-helpers/domo
+++ b/bin/ebuild-helpers/domo
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/dosbin b/bin/ebuild-helpers/dosbin
index ac0ab37ca..e92286088 100755
--- a/bin/ebuild-helpers/dosbin
+++ b/bin/ebuild-helpers/dosbin
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/dosed b/bin/ebuild-helpers/dosed
index 37c8a29d3..44752f54e 100755
--- a/bin/ebuild-helpers/dosed
+++ b/bin/ebuild-helpers/dosed
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/dosym b/bin/ebuild-helpers/dosym
index abd4da4f0..681e198c5 100755
--- a/bin/ebuild-helpers/dosym
+++ b/bin/ebuild-helpers/dosym
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/elog b/bin/ebuild-helpers/elog
index 911f8d57f..f57fce4bd 100755
--- a/bin/ebuild-helpers/elog
+++ b/bin/ebuild-helpers/elog
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/emake b/bin/ebuild-helpers/emake
index 60718a2e4..cca9cb63b 100755
--- a/bin/ebuild-helpers/emake
+++ b/bin/ebuild-helpers/emake
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
#
@@ -12,7 +12,7 @@
source "${PORTAGE_BIN_PATH}"/isolated-functions.sh || exit 1
cmd=(
- ${MAKE:-make} ${MAKEOPTS} "$@" ${EXTRA_EMAKE}
+ ${MAKE:-make} SHELL="${BASH:-/bin/bash}" ${MAKEOPTS} "$@" ${EXTRA_EMAKE}
)
if [[ ${PORTAGE_QUIET} != 1 ]] ; then
diff --git a/bin/ebuild-helpers/fowners b/bin/ebuild-helpers/fowners
index 0eda73e58..01a89dc1e 100755
--- a/bin/ebuild-helpers/fowners
+++ b/bin/ebuild-helpers/fowners
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/fperms b/bin/ebuild-helpers/fperms
index f98560039..9780e6ca8 100755
--- a/bin/ebuild-helpers/fperms
+++ b/bin/ebuild-helpers/fperms
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/keepdir b/bin/ebuild-helpers/keepdir
index a3c0c151c..9b8986a5e 100755
--- a/bin/ebuild-helpers/keepdir
+++ b/bin/ebuild-helpers/keepdir
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/newins b/bin/ebuild-helpers/newins
index 30e54b7e5..9b31a2ccf 100755
--- a/bin/ebuild-helpers/newins
+++ b/bin/ebuild-helpers/newins
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/portageq b/bin/ebuild-helpers/portageq
index d31bd6810..47640c5a8 100755
--- a/bin/ebuild-helpers/portageq
+++ b/bin/ebuild-helpers/portageq
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 2009-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
@@ -16,7 +16,7 @@ for path in ${PATH}; do
[[ ${path} == */portage/*/ebuild-helpers* ]] && continue
[[ ${path}/${scriptname} -ef ${scriptpath} ]] && continue
PYTHONPATH=${PORTAGE_PYTHONPATH:-${PORTAGE_PYM_PATH}} \
- exec "${PORTAGE_PYTHON:-/usr/bin/python}" \
+ exec "${PORTAGE_PYTHON:-@PREFIX_PORTAGE_PYTHON@}" \
"${path}/${scriptname}" "$@"
done
diff --git a/bin/ebuild-helpers/prepall b/bin/ebuild-helpers/prepall
index e23a6d410..0251e7948 100755
--- a/bin/ebuild-helpers/prepall
+++ b/bin/ebuild-helpers/prepall
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/prepalldocs b/bin/ebuild-helpers/prepalldocs
index e23a6d410..0251e7948 100755
--- a/bin/ebuild-helpers/prepalldocs
+++ b/bin/ebuild-helpers/prepalldocs
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/prepallinfo b/bin/ebuild-helpers/prepallinfo
index e23a6d410..0251e7948 100755
--- a/bin/ebuild-helpers/prepallinfo
+++ b/bin/ebuild-helpers/prepallinfo
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/prepallman b/bin/ebuild-helpers/prepallman
index e23a6d410..0251e7948 100755
--- a/bin/ebuild-helpers/prepallman
+++ b/bin/ebuild-helpers/prepallman
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/prepallstrip b/bin/ebuild-helpers/prepallstrip
index 4bde1f4b2..40764fc30 100755
--- a/bin/ebuild-helpers/prepallstrip
+++ b/bin/ebuild-helpers/prepallstrip
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/prepinfo b/bin/ebuild-helpers/prepinfo
index 9d33e6e9a..e448ac926 100755
--- a/bin/ebuild-helpers/prepinfo
+++ b/bin/ebuild-helpers/prepinfo
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/prepman b/bin/ebuild-helpers/prepman
index 4c6d47bb2..6fab36e0b 100755
--- a/bin/ebuild-helpers/prepman
+++ b/bin/ebuild-helpers/prepman
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/prepstrip b/bin/ebuild-helpers/prepstrip
index ecbea47ec..4a899ee1a 100755
--- a/bin/ebuild-helpers/prepstrip
+++ b/bin/ebuild-helpers/prepstrip
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/unprivileged/chown b/bin/ebuild-helpers/unprivileged/chown
index a7a4ff447..54174cc6c 100755
--- a/bin/ebuild-helpers/unprivileged/chown
+++ b/bin/ebuild-helpers/unprivileged/chown
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 2012-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-helpers/xattr/install b/bin/ebuild-helpers/xattr/install
index e5bb10895..b1719bcaf 100755
--- a/bin/ebuild-helpers/xattr/install
+++ b/bin/ebuild-helpers/xattr/install
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 2013-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/ebuild-ipc b/bin/ebuild-ipc
index e77b94b2c..739564d15 100755
--- a/bin/ebuild-ipc
+++ b/bin/ebuild-ipc
@@ -1,8 +1,8 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 2010-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# Use safe cwd, avoiding unsafe import for bug #469338.
cd "${PORTAGE_PYM_PATH}" || exit 1
PYTHONPATH=${PORTAGE_PYTHONPATH:-${PORTAGE_PYM_PATH}} \
- exec "${PORTAGE_PYTHON:-/usr/bin/python}" "$PORTAGE_BIN_PATH/ebuild-ipc.py" "$@"
+ exec "${PORTAGE_PYTHON:-@PREFIX_PORTAGE_PYTHON@}" "$PORTAGE_BIN_PATH/ebuild-ipc.py" "$@"
diff --git a/bin/ebuild-ipc.py b/bin/ebuild-ipc.py
index d68d3f05e..773054f5d 100755
--- a/bin/ebuild-ipc.py
+++ b/bin/ebuild-ipc.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 2010-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
#
diff --git a/bin/ebuild.sh b/bin/ebuild.sh
index cfcf6eba3..dddaada87 100755
--- a/bin/ebuild.sh
+++ b/bin/ebuild.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
@@ -220,7 +220,7 @@ debug-print() {
# default target
printf '%s\n' "${@}" >> "${T}/eclass-debug.log"
# let the portage user own/write to this file
- chgrp "${PORTAGE_GRPNAME:-portage}" "${T}/eclass-debug.log"
+ chgrp "${PORTAGE_GRPNAME:-${PORTAGE_GROUP}}" "${T}/eclass-debug.log"
chmod g+w "${T}/eclass-debug.log"
fi
}
diff --git a/bin/egencache b/bin/egencache
index d172319f8..04c8af2f0 100755
--- a/bin/egencache
+++ b/bin/egencache
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 2009-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/emaint b/bin/emaint
index df904f7c0..ea97c9b04 100755
--- a/bin/emaint
+++ b/bin/emaint
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 2005-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/emerge b/bin/emerge
index e372f5e9e..65547e390 100755
--- a/bin/emerge
+++ b/bin/emerge
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 2006-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/emerge-webrsync b/bin/emerge-webrsync
index db39b272e..6ac7e3328 100755
--- a/bin/emerge-webrsync
+++ b/bin/emerge-webrsync
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# Author: Karl Trygve Kalleberg <karltk@gentoo.org>
@@ -51,9 +51,15 @@ eval "$("${portageq}" envvar -v DISTDIR EPREFIX FEATURES \
PORTAGE_BIN_PATH PORTAGE_CONFIGROOT PORTAGE_GPG_DIR \
PORTAGE_NICENESS PORTAGE_REPOSITORIES PORTAGE_RSYNC_EXTRA_OPTS \
PORTAGE_RSYNC_OPTS PORTAGE_TEMP_GPG_DIR PORTAGE_TMPDIR \
- USERLAND http_proxy ftp_proxy)"
+ USERLAND http_proxy ftp_proxy \
+ PORTAGE_USER PORTAGE_GROUP)"
export http_proxy ftp_proxy
+# PREFIX LOCAL: use Prefix servers, just because we want this and infra
+# can't support us yet
+GENTOO_MIRRORS="http://rsync.prefix.bitzolder.nl"
+# END PREFIX LOCAL
+
source "${PORTAGE_BIN_PATH}"/isolated-functions.sh || exit 1
repo_name=gentoo
@@ -247,7 +253,9 @@ sync_local() {
__vecho "Syncing local tree ..."
- local ownership="portage:portage"
+ # PREFIX LOCAL: use PORTAGE_USER and PORTAGE_GROUP
+ local ownership="${PORTAGE_USER:-portage}:${PORTAGE_GROUP:-portage}"
+ # END PREFIX LOCAL
if has usersync ${FEATURES} ; then
case "${USERLAND}" in
BSD)
diff --git a/bin/emirrordist b/bin/emirrordist
index 3ea08379e..866a2be65 100755
--- a/bin/emirrordist
+++ b/bin/emirrordist
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 2013-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/env-update b/bin/env-update
index 2256b37f5..6ffadc638 100755
--- a/bin/env-update
+++ b/bin/env-update
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/etc-update b/bin/etc-update
index 7897d9b16..773db2daa 100755
--- a/bin/etc-update
+++ b/bin/etc-update
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
@@ -32,7 +32,7 @@ get_config() {
"${PORTAGE_CONFIGROOT}"etc/etc-update.conf)
}
-OS_RELEASE_POSSIBLE_IDS=$(source /etc/os-release >/dev/null 2>&1; echo ":${ID}:${ID_LIKE//[[:space:]]/:}:")
+OS_RELEASE_POSSIBLE_IDS=$(source "@PORTAGE_EPREFIX@"/etc/os-release >/dev/null 2>&1; echo ":${ID}:${ID_LIKE//[[:space:]]/:}:")
case ${OS_RELEASE_POSSIBLE_IDS} in
*:suse:*|*:opensuse:*|*:opensuse-tumbleweed:*) OS_FAMILY='rpm';;
diff --git a/bin/filter-bash-environment.py b/bin/filter-bash-environment.py
index 045ea6f52..06cac7214 100755
--- a/bin/filter-bash-environment.py
+++ b/bin/filter-bash-environment.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/fixpackages b/bin/fixpackages
index a291e013d..f43506600 100755
--- a/bin/fixpackages
+++ b/bin/fixpackages
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/glsa-check b/bin/glsa-check
index eff01cf31..f9dae110f 100755
--- a/bin/glsa-check
+++ b/bin/glsa-check
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 1999-2019 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/helper-functions.sh b/bin/helper-functions.sh
index f76703f0c..34cbc3eec 100644
--- a/bin/helper-functions.sh
+++ b/bin/helper-functions.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/install-qa-check.d/05prefix b/bin/install-qa-check.d/05prefix
index e1fc2bd99..03da3bbce 100644
--- a/bin/install-qa-check.d/05prefix
+++ b/bin/install-qa-check.d/05prefix
@@ -3,24 +3,24 @@
install_qa_check_prefix() {
[[ ${ED} == ${D} ]] && return
- if [[ -d ${ED}/${D} ]] ; then
- find "${ED}/${D}" | \
+ if [[ -d ${ED%/}${D%/} ]] ; then
+ find "${ED%/}${D%/}/" | \
while read i ; do
- eqawarn "QA Notice: /${i##${ED}/${D}} installed in \${ED}/\${D}"
+ eqawarn "QA Notice: /${i#${ED%/}${D%/}/} installed in \${ED}\${D}"
done
- die "Aborting due to QA concerns: files installed in ${ED}/${D}"
+ die "Aborting due to QA concerns: files installed in ${ED%/}${D%/}/"
fi
- if [[ -d ${ED}/${EPREFIX} ]] ; then
- find "${ED}/${EPREFIX}/" | \
+ if [[ -d ${ED%/}${EPREFIX} ]] ; then
+ find "${ED%/}${EPREFIX}/" | \
while read i ; do
- eqawarn "QA Notice: ${i#${D}} double prefix"
+ eqawarn "QA Notice: ${i#${D%/}/} double prefix"
done
die "Aborting due to QA concerns: double prefix files installed"
fi
- if [[ -d ${D} ]] ; then
- INSTALLTOD=$(find ${D%/} | egrep -v "^${ED}" | sed -e "s|^${D%/}||" | awk '{if (length($0) <= length("'"${EPREFIX}"'")) { if (substr("'"${EPREFIX}"'", 1, length($0)) != $0) {print $0;} } else if (substr($0, 1, length("'"${EPREFIX}"'")) != "'"${EPREFIX}"'") {print $0;} }')
+ if [[ -d ${D%/}/ ]] ; then
+ INSTALLTOD=$(find ${D%/} | egrep -v "^${ED%/}/" | sed -e "s|^${D%/}||" | awk '{if (length($0) <= length("'"${EPREFIX}"'")) { if (substr("'"${EPREFIX}"'", 1, length($0)) != $0) {print $0;} } else if (substr($0, 1, length("'"${EPREFIX}"'")) != "'"${EPREFIX}"'") {print $0;} }')
if [[ -n ${INSTALLTOD} ]] ; then
eqawarn "QA Notice: the following files are outside of the prefix:"
eqawarn "${INSTALLTOD}"
@@ -34,8 +34,23 @@ install_qa_check_prefix() {
# check shebangs, bug #282539
rm -f "${T}"/non-prefix-shebangs-errs
local WHITELIST=" /usr/bin/env "
+ # shebang can be an absolutised path, bug #342929
+ local eprefix=$(canonicalize ${EPREFIX})
+ # Without the stacked-prefix feature, tests using BPREFIX
+ # are redundant to EPREFIX, but run only if we will fail.
+ # Otherways, BPREFIX really is BROOT (the EAPI 7 one).
+ local BPREFIX=${EPREFIX}
+ local bprefix=${eprefix}
+ if has stacked-prefix ${FEATURES} &&
+ [[ -z ${ROOT%/} ]] &&
+ [[ ${CBUILD} == ${CHOST} ]] &&
+ [[ ${EPREFIX} != ${BROOT-${PORTAGE_OVERRIDE_EPREFIX}} ]] &&
+ :; then
+ BPREFIX=${BROOT-${PORTAGE_OVERRIDE_EPREFIX}}
+ bprefix=$(canonicalize ${BPREFIX})
+ fi
# this is hell expensive, but how else?
- find "${ED}" -executable \! -type d -print0 \
+ find "${ED%/}/" -executable \! -type d -print0 \
| xargs -0 grep -H -n -m1 "^#!" \
| while read f ;
do
@@ -49,9 +64,7 @@ install_qa_check_prefix() {
line=( ${line#"#!"} )
IFS=${oldIFS}
[[ ${WHITELIST} == *" ${line[0]} "* ]] && continue
- local fp=${fn#${D}} ; fp=/${fp%/*}
- # line[0] can be an absolutised path, bug #342929
- local eprefix=$(canonicalize ${EPREFIX})
+ local fp=${fn#${D%/}/} ; fp=/${fp%/*}
local rf=${fn}
# in case we deal with a symlink, make sure we don't replace it
# with a real file (sed -i does that)
@@ -60,45 +73,56 @@ install_qa_check_prefix() {
[[ ${rf} != /* ]] && rf=${fn%/*}/${rf}
# ignore symlinks pointing to outside prefix
# as seen in sys-devel/native-cctools
- [[ $(canonicalize "/${rf#${D}}") != ${eprefix}/* ]] && continue
+ [[ $(canonicalize "/${rf#${D%/}/}") != ${eprefix}/* ]] && continue
fi
# does the shebang start with ${EPREFIX}, and does it exist?
- if [[ ${line[0]} == ${EPREFIX}/* || ${line[0]} == ${eprefix}/* ]] ; then
+ if [[ ${line[0]} == ${EPREFIX}/* || ${line[0]} == ${eprefix}/* ]] \
+ || [[ ${line[0]} == ${BPREFIX}/* || ${line[0]} == ${bprefix}/* ]] ; then
if [[ ! -e ${ROOT%/}${line[0]} && ! -e ${D%/}${line[0]} ]] ; then
# hmm, refers explicitly to $EPREFIX, but doesn't exist,
# if it's in PATH that's wrong in any case
if [[ ":${PATH}:" == *":${fp}:"* ]] ; then
- echo "${fn#${D}}:${line[0]} (explicit EPREFIX but target not found)" \
+ echo "${fn#${D%/}/}:${line[0]} (explicit EPREFIX but target not found)" \
>> "${T}"/non-prefix-shebangs-errs
else
- eqawarn "${fn#${D}} has explicit EPREFIX in shebang but target not found (${line[0]})"
+ eqawarn "${fn#${D%/}/} has explicit EPREFIX in shebang but target not found (${line[0]})"
fi
fi
continue
fi
- # unprefixed shebang, is the script directly in $PATH?
- if [[ ":${PATH}:" == *":${fp}:"* ]] ; then
- if [[ -e ${EROOT}${line[0]} || -e ${ED}${line[0]} ]] ; then
+ # unprefixed shebang, is the script directly in $PATH or an init
+ # script?
+ if [[ ":${PATH}:${EPREFIX}/etc/init.d:" == *":${fp}:"* ]] ; then
+ local foundprefix="none"
+ if [[ -e ${EROOT%/}${line[0]} || -e ${ED%/}${line[0]} ]] ; then
+ # is it unprefixed, but we can just fix it because an
+ # eprefixed variant exists
+ eqawarn "eprefixing shebang of ${fn#${D%/}/}"
+ foundprefix=${EPREFIX}
+ elif [[ -e ${BPREFIX}${line[0]} ]] ; then
# is it unprefixed, but we can just fix it because a
- # prefixed variant exists
- eqawarn "prefixing shebang of ${fn#${D}}"
+ # bprefixed variant exists
+ eqawarn "bprefixing shebang of ${fn#${D%/}/}"
+ foundprefix=${BPREFIX}
+ fi
+ if [[ ${foundprefix} != "none" ]] ; then
# statement is made idempotent on purpose, because
# symlinks may point to the same target, and hence the
# same real file may be sedded multiple times since we
# read the shebangs in one go upfront for performance
# reasons
- sed -i -e '1s:^#! \?'"${line[0]}"':#!'"${EPREFIX}"${line[0]}':' "${rf}"
+ sed -i -e '1s:^#! \?'"${line[0]}"':#!'"${foundprefix}"${line[0]}':' "${rf}"
continue
else
# this is definitely wrong: script in $PATH and invalid shebang
- echo "${fn#${D}}:${line[0]} (script ${fn##*/} installed in PATH but interpreter ${line[0]} not found)" \
+ echo "${fn#${D%/}/}:${line[0]} (script ${fn##*/} installed in PATH but interpreter ${line[0]} not found)" \
>> "${T}"/non-prefix-shebangs-errs
fi
else
# unprefixed/invalid shebang, but outside $PATH, this may be
# intended (e.g. config.guess) so remain silent by default
has stricter ${FEATURES} && \
- eqawarn "invalid shebang in ${fn#${D}}: ${line[0]}"
+ eqawarn "invalid shebang in ${fn#${D%/}/}: ${line[0]}"
fi
done
if [[ -e "${T}"/non-prefix-shebangs-errs ]] ; then
diff --git a/bin/install-qa-check.d/80libraries b/bin/install-qa-check.d/80libraries
index d1d2c4fdd..7ab419803 100644
--- a/bin/install-qa-check.d/80libraries
+++ b/bin/install-qa-check.d/80libraries
@@ -140,7 +140,11 @@ lib_check() {
local abort="no"
local a s
for a in "${ED%/}"/usr/lib*/*.a ; do
- s=${a%.a}.so
+ # PREFIX LOCAL: support MachO objects
+ [[ ${CHOST} == *-darwin* ]] \
+ && s=${a%.a}.dylib \
+ || s=${a%.a}.so
+ # END PREFIX LOCAL
if [[ ! -e ${s} ]] ; then
s=${s%usr/*}${s##*/usr/}
if [[ -e ${s} ]] ; then
@@ -153,7 +157,12 @@ lib_check() {
[[ ${abort} == "yes" ]] && die "add those ldscripts"
# Make sure people don't store libtool files or static libs in /lib
- f=$(ls "${ED%/}"/lib*/*.{a,la} 2>/dev/null)
+ # PREFIX LOCAL: on AIX, "dynamic libs" have extension .a, so don't
+ # get false positives
+ [[ ${CHOST} == *-aix* ]] \
+ && f=$(ls "${ED%/}"lib*/*.la 2>/dev/null || true) \
+ || f=$(ls "${ED%/}"lib*/*.{a,la} 2>/dev/null)
+ # END PREFIX LOCAL
if [[ -n ${f} ]] ; then
__vecho -ne '\n'
eqawarn "QA Notice: Excessive files found in the / partition"
diff --git a/bin/install-qa-check.d/80multilib-strict b/bin/install-qa-check.d/80multilib-strict
index afd223250..6c705bf16 100644
--- a/bin/install-qa-check.d/80multilib-strict
+++ b/bin/install-qa-check.d/80multilib-strict
@@ -1,7 +1,7 @@
# Strict multilib directory checks
multilib_strict_check() {
if has multilib-strict ${FEATURES} && \
- [[ -x /usr/bin/file && -x /usr/bin/find ]] && \
+ [[ -x ${EPREFIX}/usr/bin/file && -x ${EPREFIX}/usr/bin/find ]] && \
[[ -n ${MULTILIB_STRICT_DIRS} && -n ${MULTILIB_STRICT_DENY} ]]
then
rm -f "${T}/multilib-strict.log"
diff --git a/bin/install-qa-check.d/90gcc-warnings b/bin/install-qa-check.d/90gcc-warnings
index bde198c97..3c737b51e 100644
--- a/bin/install-qa-check.d/90gcc-warnings
+++ b/bin/install-qa-check.d/90gcc-warnings
@@ -115,7 +115,7 @@ gcc_warn_check() {
[[ $reset_debug = 1 ]] && set -x
# Use safe cwd, avoiding unsafe import for bug #469338.
f=$(cd "${PORTAGE_PYM_PATH}" ; $cat_cmd "${PORTAGE_LOG_FILE}" | \
- "${PORTAGE_PYTHON:-/usr/bin/python}" "$PORTAGE_BIN_PATH"/check-implicit-pointer-usage.py || die "check-implicit-pointer-usage.py failed")
+ "${PORTAGE_PYTHON:-@PREFIX_PORTAGE_PYTHON@}" "$PORTAGE_BIN_PATH"/check-implicit-pointer-usage.py || die "check-implicit-pointer-usage.py failed")
if [[ -n ${f} ]] ; then
# In the future this will be a forced "die". In preparation,
diff --git a/bin/install-qa-check.d/90world-writable b/bin/install-qa-check.d/90world-writable
index 820683bd6..90b961a86 100644
--- a/bin/install-qa-check.d/90world-writable
+++ b/bin/install-qa-check.d/90world-writable
@@ -2,7 +2,9 @@
world_writable_check() {
# Now we look for all world writable files.
- local unsafe_files=$(find "${ED}" -type f -perm -2 | sed -e "s:^${ED}:/:")
+ # PREFIX LOCAL: keep offset prefix in the reported files
+ local unsafe_files=$(find "${ED}" -type f -perm -2 | sed -e "s:^${D}:/:")
+ # END PREFIX LOCAL
local OLDIFS x prev_shopts=$-
OLDIFS=$IFS
@@ -19,7 +21,9 @@ world_writable_check() {
eqawarn
fi
- local unsafe_files=$(find "${ED}" -type f '(' -perm -2002 -o -perm -4002 ')' | sed -e "s:^${ED}:/:")
+ # PREFIX LOCAL: keep offset prefix in the reported files
+ local unsafe_files=$(find "${ED}" -type f '(' -perm -2002 -o -perm -4002 ')' | sed -e "s:^${D}:/:")
+ # END PREFIX LOCAL
if [[ -n ${unsafe_files} ]] ; then
eqawarn "QA Notice: Unsafe files detected (set*id and world writable)"
diff --git a/bin/install.py b/bin/install.py
index 495534d33..03a4511bb 100755
--- a/bin/install.py
+++ b/bin/install.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 2013-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/isolated-functions.sh b/bin/isolated-functions.sh
index fde684013..7840d6012 100644
--- a/bin/isolated-functions.sh
+++ b/bin/isolated-functions.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
@@ -425,16 +425,22 @@ case "${NOCOLOR:-false}" in
;;
esac
-if [[ -z ${USERLAND} ]] ; then
- case $(uname -s) in
- *BSD|DragonFly)
- export USERLAND="BSD"
- ;;
- *)
- export USERLAND="GNU"
- ;;
- esac
-fi
+# In Prefix every platform has USERLAND=GNU, even FreeBSD. Since I
+# don't know how to reliably "figure out" we are in a Prefix instance of
+# portage here, I for now disable this check, and hardcode it to GNU.
+# Somehow it appears stange to me that this code is in this file,
+# non-ebuilds/eclasses should never rely on USERLAND and XARGS, don't they?
+#if [[ -z ${USERLAND} ]] ; then
+# case $(uname -s) in
+# *BSD|DragonFly)
+# export USERLAND="BSD"
+# ;;
+# *)
+# export USERLAND="GNU"
+# ;;
+# esac
+#fi
+[[ -z ${USERLAND} ]] && USERLAND="GNU"
if [[ -z ${XARGS} ]] ; then
case ${USERLAND} in
diff --git a/bin/lock-helper.py b/bin/lock-helper.py
index aa2dd60fa..427c1380b 100755
--- a/bin/lock-helper.py
+++ b/bin/lock-helper.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 2010-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh
index c2a16cbe0..d01a8edb1 100755
--- a/bin/misc-functions.sh
+++ b/bin/misc-functions.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
#
@@ -19,6 +19,10 @@ source "${PORTAGE_BIN_PATH}/ebuild.sh" || exit 1
install_symlink_html_docs() {
if ! ___eapi_has_prefix_variables; then
local ED=${D}
+ else
+ # PREFIX LOCAL: ED needs not to exist, whereas D does
+ [[ ! -d ${ED} && -d ${D} ]] && dodir /
+ # END PREFIX LOCAL
fi
cd "${ED}" || die "cd failed"
#symlink the html documentation (if DOC_SYMLINKS_DIR is set in make.conf)
@@ -83,7 +87,9 @@ install_qa_check() {
local EPREFIX= ED=${D}
fi
- cd "${ED}" || die "cd failed"
+ # PREFIX LOCAL: ED needs not to exist, whereas D does
+ cd "${D}" || die "cd failed"
+ # END PREFIX LOCAL
# Collect the paths for QA checks, highest prio first.
paths=(
@@ -170,6 +176,39 @@ install_qa_check() {
mtree -U -e -p "${ED}" -k flags < "${T}/bsdflags.mtree" &> /dev/null
fi
+ # PREFIX LOCAL:
+ # anything outside the prefix should be caught by the Prefix QA
+ # check, so if there's nothing in ED, we skip searching for QA
+ # checks there, the specific QA funcs can hence rely on ED existing
+ if [[ -d ${ED} ]] ; then
+ case ${CHOST} in
+ *-darwin*)
+ # Mach-O platforms (NeXT, Darwin, OSX)
+ install_qa_check_macho
+ ;;
+ *-interix*|*-winnt*)
+ # PECOFF platforms (Windows/Interix)
+ install_qa_check_pecoff
+ ;;
+ *-aix*)
+ # XCOFF platforms (AIX)
+ install_qa_check_xcoff
+ ;;
+ *)
+ # because this is the majority: ELF platforms (Linux,
+ # Solaris, *BSD, IRIX, etc.)
+ install_qa_check_elf
+ ;;
+ esac
+ fi
+
+ # this is basically here such that the diff with trunk remains just
+ # offsetted and not out of order
+ install_qa_check_misc
+ # END PREFIX LOCAL
+}
+
+install_qa_check_elf() {
# Create NEEDED.ELF.2 regardless of RESTRICT=binchecks, since this info is
# too useful not to have (it's required for things like preserve-libs), and
# it's tempting for ebuild authors to set RESTRICT=binchecks for packages
@@ -207,11 +246,396 @@ install_qa_check() {
eqawarn "$(while read -r x; do x=${x#*;} ; x=${x%%;*} ; echo "${x#${EPREFIX}}" ; done < "${PORTAGE_BUILDDIR}"/build-info/NEEDED.ELF.2)"
fi
fi
+}
+install_qa_check_misc() {
# Portage regenerates this on the installed system.
rm -f "${ED%/}"/usr/share/info/dir{,.gz,.bz2} || die "rm failed!"
}
+install_qa_check_macho() {
+ if ! has binchecks ${RESTRICT} ; then
+ # on Darwin, dynamic libraries are called .dylibs instead of
+ # .sos. In addition the version component is before the
+ # extension, not after it. Check for this, and *only* warn
+ # about it. Some packages do ship .so files on Darwin and make
+ # it work (ugly!).
+ rm -f "${T}/mach-o.check"
+ find ${ED%/} -name "*.so" -or -name "*.so.*" | \
+ while read i ; do
+ [[ $(file $i) == *"Mach-O"* ]] && \
+ echo "${i#${D}}" >> "${T}/mach-o.check"
+ done
+ if [[ -f ${T}/mach-o.check ]] ; then
+ f=$(< "${T}/mach-o.check")
+ __vecho -ne '\a\n'
+ eqawarn "QA Notice: Found .so dynamic libraries on Darwin:"
+ eqawarn " ${f//$'\n'/\n }"
+ fi
+ rm -f "${T}/mach-o.check"
+
+ # The naming for dynamic libraries is different on Darwin; the
+ # version component is before the extention, instead of after
+ # it, as with .sos. Again, make this a warning only.
+ rm -f "${T}/mach-o.check"
+ find ${ED%/} -name "*.dylib.*" | \
+ while read i ; do
+ echo "${i#${D}}" >> "${T}/mach-o.check"
+ done
+ if [[ -f "${T}/mach-o.check" ]] ; then
+ f=$(< "${T}/mach-o.check")
+ __vecho -ne '\a\n'
+ eqawarn "QA Notice: Found wrongly named dynamic libraries on Darwin:"
+ eqawarn " ${f// /\n }"
+ fi
+ rm -f "${T}/mach-o.check"
+ fi
+
+ install_name_is_relative() {
+ case $1 in
+ "@executable_path/"*) return 0 ;;
+ "@loader_path"/*) return 0 ;;
+ "@rpath/"*) return 0 ;;
+ *) return 1 ;;
+ esac
+ }
+
+ # While we generate the NEEDED files, check that we don't get kernel
+ # traps at runtime because of broken install_names on Darwin.
+ rm -f "${T}"/.install_name_check_failed
+ scanmacho -qyRF '%a;%p;%S;%n' "${D}" | { while IFS= read l ; do
+ arch=${l%%;*}; l=${l#*;}
+ obj="/${l%%;*}"; l=${l#*;}
+ install_name=${l%%;*}; l=${l#*;}
+ needed=${l%%;*}; l=${l#*;}
+
+ ignore=
+ qa_var="QA_IGNORE_INSTALL_NAME_FILES_${ARCH/-/_}"
+ eval "[[ -n \${!qa_var} ]] &&
+ QA_IGNORE_INSTALL_NAME_FILES=(\"\${${qa_var}[@]}\")"
+
+ if [[ ${#QA_IGNORE_INSTALL_NAME_FILES[@]} -gt 1 ]] ; then
+ for x in "${QA_IGNORE_INSTALL_NAME_FILES[@]}" ; do
+ [[ ${obj##*/} == ${x} ]] && \
+ ignore=true
+ done
+ else
+ local shopts=$-
+ set -o noglob
+ for x in ${QA_IGNORE_INSTALL_NAME_FILES} ; do
+ [[ ${obj##*/} == ${x} ]] && \
+ ignore=true
+ done
+ set +o noglob
+ set -${shopts}
+ fi
+
+ # See if the self-reference install_name points to an existing
+ # and to be installed file. This usually is a symlink for the
+ # major version.
+ if install_name_is_relative ${install_name} ; then
+ # try to locate the library in the installed image
+ local inpath=${install_name#@*/}
+ local libl
+ for libl in $(find "${ED}" -name "${inpath##*/}") ; do
+ if [[ ${libl} == */${inpath} ]] ; then
+ install_name=/${libl#${D}}
+ break
+ fi
+ done
+ fi
+ if [[ ! -e ${D}${install_name} ]] ; then
+ eqawarn "QA Notice: invalid self-reference install_name ${install_name} in ${obj}"
+ # remember we are in an implicit subshell, that's
+ # why we touch a file here ... ideally we should be
+ # able to die correctly/nicely here
+ [[ -z ${ignore} ]] && touch "${T}"/.install_name_check_failed
+ fi
+
+ # this is ugly, paths with spaces won't work
+ for lib in ${needed//,/ } ; do
+ if [[ ${lib} == ${D}* ]] ; then
+ eqawarn "QA Notice: install_name references \${D}: ${lib} in ${obj}"
+ [[ -z ${ignore} ]] && touch "${T}"/.install_name_check_failed
+ elif [[ ${lib} == ${S}* ]] ; then
+ eqawarn "QA Notice: install_name references \${S}: ${lib} in ${obj}"
+ [[ -z ${ignore} ]] && touch "${T}"/.install_name_check_failed
+ elif ! install_name_is_relative ${lib} && [[ ! -e ${lib} && ! -e ${D}${lib} ]] ; then
+ eqawarn "QA Notice: invalid reference to ${lib} in ${obj}"
+ [[ -z ${ignore} ]] && touch "${T}"/.install_name_check_failed
+ fi
+ done
+
+ # backwards compatibility
+ echo "${obj} ${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED
+ # what we use
+ echo "${arch};${obj};${install_name};${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.MACHO.3
+ done }
+ if [[ -f ${T}/.install_name_check_failed ]] ; then
+ # secret switch "allow_broken_install_names" to get
+ # around this and install broken crap (not a good idea)
+ has allow_broken_install_names ${FEATURES} || \
+ die "invalid install_name found, your application or library will crash at runtime"
+ fi
+}
+
+install_qa_check_pecoff() {
+ local _pfx_scan="readpecoff ${CHOST}"
+
+ # this one uses readpecoff, which supports multiple prefix platforms!
+ # this is absolutely _not_ optimized for speed, and there may be plenty
+ # of possibilities by introducing one or the other cache!
+ if ! has binchecks ${RESTRICT}; then
+ # copied and adapted from the above scanelf code.
+ local qa_var insecure_rpath=0 tmp_quiet=${PORTAGE_QUIET}
+ local f x
+
+ # display warnings when using stricter because we die afterwards
+ if has stricter ${FEATURES} ; then
+ unset PORTAGE_QUIET
+ fi
+
+ local _exec_find_opt="-executable"
+ [[ ${CHOST} == *-winnt* ]] && _exec_find_opt='-name *.dll -o -name *.exe'
+
+ # Make sure we disallow insecure RUNPATH/RPATH's
+ # Don't want paths that point to the tree where the package was built
+ # (older, broken libtools would do this). Also check for null paths
+ # because the loader will search $PWD when it finds null paths.
+
+ f=$(
+ find "${ED}" -type f '(' ${_exec_find_opt} ')' -print0 | xargs -0 ${_pfx_scan} | \
+ while IFS=";" read arch obj soname rpath needed ; do \
+ echo "${rpath}" | grep -E "(${PORTAGE_BUILDDIR}|: |::|^:|^ )" > /dev/null 2>&1 \
+ && echo "${obj}"; done;
+ )
+ # Reject set*id binaries with $ORIGIN in RPATH #260331
+ x=$(
+ find "${ED}" -type f '(' -perm -u+s -o -perm -g+s ')' -print0 | \
+ xargs -0 ${_pfx_scan} | while IFS=";" read arch obj soname rpath needed; do \
+ echo "${rpath}" | grep '$ORIGIN' > /dev/null 2>&1 && echo "${obj}"; done;
+ )
+ if [[ -n ${f}${x} ]] ; then
+ __vecho -ne '\a\n'
+ eqawarn "QA Notice: The following files contain insecure RUNPATH's"
+ eqawarn " Please file a bug about this at http://bugs.gentoo.org/"
+ eqawarn " with the maintaining herd of the package."
+ eqawarn "${f}${f:+${x:+\n}}${x}"
+ __vecho -ne '\a\n'
+ if [[ -n ${x} ]] || has stricter ${FEATURES} ; then
+ insecure_rpath=1
+ else
+ eqawarn "cannot automatically fix runpaths on interix platforms!"
+ fi
+ fi
+
+ rm -f "${PORTAGE_BUILDDIR}"/build-info/NEEDED
+ rm -f "${PORTAGE_BUILDDIR}"/build-info/NEEDED.PECOFF.1
+
+ # Save NEEDED information after removing self-contained providers
+ find "${ED}" -type f '(' ${_exec_find_opt} ')' -print0 | xargs -0 ${_pfx_scan} | { while IFS=';' read arch obj soname rpath needed; do
+ # need to strip image dir from object name.
+ obj="/${obj#${D}}"
+ if [ -z "${rpath}" -o -n "${rpath//*ORIGIN*}" ]; then
+ # object doesn't contain $ORIGIN in its runpath attribute
+ echo "${obj} ${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED
+ echo "${arch};${obj};${soname};${rpath};${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.PECOFF.1
+ else
+ dir=${obj%/*}
+ # replace $ORIGIN with the dirname of the current object for the lookup
+ opath=$(echo :${rpath}: | sed -e "s#.*:\(.*\)\$ORIGIN\(.*\):.*#\1${dir}\2#")
+ sneeded=$(echo ${needed} | tr , ' ')
+ rneeded=""
+ for lib in ${sneeded}; do
+ found=0
+ for path in ${opath//:/ }; do
+ [ -e "${ED}/${path}/${lib}" ] && found=1 && break
+ done
+ [ "${found}" -eq 0 ] && rneeded="${rneeded},${lib}"
+ done
+ rneeded=${rneeded:1}
+ if [ -n "${rneeded}" ]; then
+ echo "${obj} ${rneeded}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED
+ echo "${arch};${obj};${soname};${rpath};${rneeded}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.PECOFF.1
+ fi
+ fi
+ done }
+
+ if [[ ${insecure_rpath} -eq 1 ]] ; then
+ die "Aborting due to serious QA concerns with RUNPATH/RPATH"
+ elif [[ -n ${die_msg} ]] && has stricter ${FEATURES} ; then
+ die "Aborting due to QA concerns: ${die_msg}"
+ fi
+
+ local _so_ext='.so*'
+
+ case "${CHOST}" in
+ *-winnt*) _so_ext=".dll" ;; # no "*" intentionally!
+ esac
+
+ # Run some sanity checks on shared libraries
+ for d in "${ED}"lib* "${ED}"usr/lib* ; do
+ [[ -d "${d}" ]] || continue
+ f=$(find "${d}" -name "lib*${_so_ext}" -print0 | \
+ xargs -0 ${_pfx_scan} | while IFS=";" read arch obj soname rpath needed; \
+ do [[ -z "${soname}" ]] && echo "${obj}"; done)
+ if [[ -n ${f} ]] ; then
+ __vecho -ne '\a\n'
+ eqawarn "QA Notice: The following shared libraries lack a SONAME"
+ eqawarn "${f}"
+ __vecho -ne '\a\n'
+ sleep 1
+ fi
+
+ f=$(find "${d}" -name "lib*${_so_ext}" -print0 | \
+ xargs -0 ${_pfx_scan} | while IFS=";" read arch obj soname rpath needed; \
+ do [[ -z "${needed}" ]] && echo "${obj}"; done)
+ if [[ -n ${f} ]] ; then
+ __vecho -ne '\a\n'
+ eqawarn "QA Notice: The following shared libraries lack NEEDED entries"
+ eqawarn "${f}"
+ __vecho -ne '\a\n'
+ sleep 1
+ fi
+ done
+
+ PORTAGE_QUIET=${tmp_quiet}
+ fi
+}
+
+install_qa_check_xcoff() {
+ if ! has binchecks ${RESTRICT}; then
+ local tmp_quiet=${PORTAGE_QUIET}
+ local queryline deplib
+ local insecure_rpath_list= undefined_symbols_list=
+
+ # display warnings when using stricter because we die afterwards
+ if has stricter ${FEATURES} ; then
+ unset PORTAGE_QUIET
+ fi
+
+ rm -f "${PORTAGE_BUILDDIR}"/build-info/NEEDED.XCOFF.1
+
+ local neededfd
+ for neededfd in {3..1024} none; do ( : <&${neededfd} ) 2>/dev/null || break; done
+ [[ ${neededfd} != none ]] || die "cannot find free file descriptor handle"
+
+ eval "exec ${neededfd}>\"${PORTAGE_BUILDDIR}\"/build-info/NEEDED.XCOFF.1" || die "cannot open ${PORTAGE_BUILDDIR}/build-info/NEEDED.XCOFF.1"
+
+ ( # work around a problem in /usr/bin/dump (used by aixdll-query)
+ # dumping core when path names get too long.
+ cd "${ED}" >/dev/null &&
+ find . -not -type d -exec \
+ aixdll-query '{}' FILE MEMBER FLAGS FORMAT RUNPATH DEPLIBS ';'
+ ) > "${T}"/needed 2>/dev/null
+
+ # Symlinking shared archive libraries is not a good idea on aix,
+ # as there is nothing like "soname" on pure filesystem level.
+ # So we create a copy instead of the symlink.
+ local prev_FILE=
+ local FILE MEMBER FLAGS FORMAT RUNPATH DEPLIBS
+ while read queryline
+ do
+ FILE= MEMBER= FLAGS= FORMAT= RUNPATH= DEPLIBS=
+ eval ${queryline}
+ FILE=${FILE#./}
+
+ if [[ ${prev_FILE} != ${FILE} ]]; then
+ if [[ " ${FLAGS} " == *" SHROBJ "* && -h ${ED}${FILE} ]]; then
+ prev_FILE=${FILE}
+ local target=$(readlink "${ED}${FILE}")
+ if [[ ${target} == /* ]]; then
+ target=${D}${target}
+ else
+ target=${FILE%/*}/${target}
+ fi
+ rm -f "${ED}${FILE}" || die "cannot prune ${FILE}"
+ cp -f "${ED}${target}" "${ED}${FILE}" || die "cannot copy ${target} to ${FILE}"
+ fi
+ fi
+ done <"${T}"/needed
+
+ prev_FILE=
+ while read queryline
+ do
+ FILE= MEMBER= FLAGS= FORMAT= RUNPATH= DEPLIBS=
+ eval ${queryline}
+ FILE=${FILE#./}
+
+ if [[ -n ${MEMBER} && ${prev_FILE} != ${FILE} ]]; then
+ # Save NEEDED information for each archive library stub
+ # even if it is static only: the already installed archive
+ # may contain shared objects to be preserved.
+ echo "${FORMAT##* }${FORMAT%%-*};${EPREFIX}/${FILE};${FILE##*/};;" >&${neededfd}
+ fi
+ prev_FILE=${FILE}
+
+ # shared objects have both EXEC and SHROBJ flags,
+ # while executables have EXEC flag only.
+ [[ " ${FLAGS} " == *" EXEC "* ]] || continue
+
+ # Make sure we disallow insecure RUNPATH's
+ # Don't want paths that point to the tree where the package was built
+ # (older, broken libtools would do this). Also check for null paths
+ # because the loader will search $PWD when it finds null paths.
+ # And we really want absolute paths only.
+ if [[ -n $(echo ":${RUNPATH}:" | grep -E "(${PORTAGE_BUILDDIR}|::|:[^/])") ]]; then
+ insecure_rpath_list="${insecure_rpath_list}\n${FILE}${MEMBER:+[${MEMBER}]}"
+ fi
+
+ local needed=
+ [[ -n ${MEMBER} ]] && needed=${FILE##*/}
+ for deplib in ${DEPLIBS}; do
+ eval deplib=${deplib}
+ if [[ ${deplib} == '.' || ${deplib} == '..' ]]; then
+ # Although we do have runtime linking, we don't want undefined symbols.
+ # AIX does indicate this by needing either '.' or '..'
+ undefined_symbols_list="${undefined_symbols_list}\n${FILE}"
+ else
+ needed="${needed}${needed:+,}${deplib}"
+ fi
+ done
+
+ FILE=${EPREFIX}/${FILE}
+
+ [[ -n ${MEMBER} ]] && MEMBER="[${MEMBER}]"
+ # Save NEEDED information
+ echo "${FORMAT##* }${FORMAT%%-*};${FILE}${MEMBER};${FILE##*/}${MEMBER};${RUNPATH};${needed}" >&${neededfd}
+ done <"${T}"/needed
+
+ eval "exec ${neededfd}>&-" || die "cannot close handle to ${PORTAGE_BUILDDIR}/build-info/NEEDED.XCOFF.1"
+
+ if [[ -n ${undefined_symbols_list} ]]; then
+ __vecho -ne '\a\n'
+ eqawarn "QA Notice: The following files contain undefined symbols."
+ eqawarn " Please file a bug about this at http://bugs.gentoo.org/"
+ eqawarn " with 'prefix' as the maintaining herd of the package."
+ eqawarn "${undefined_symbols_list}"
+ __vecho -ne '\a\n'
+ fi
+
+ if [[ -n ${insecure_rpath_list} ]] ; then
+ __vecho -ne '\a\n'
+ eqawarn "QA Notice: The following files contain insecure RUNPATH's"
+ eqawarn " Please file a bug about this at http://bugs.gentoo.org/"
+ eqawarn " with 'prefix' as the maintaining herd of the package."
+ eqawarn "${insecure_rpath_list}"
+ __vecho -ne '\a\n'
+ if has stricter ${FEATURES} ; then
+ insecure_rpath=1
+ fi
+ fi
+
+ if [[ ${insecure_rpath} -eq 1 ]] ; then
+ die "Aborting due to serious QA concerns with RUNPATH/RPATH"
+ elif [[ -n ${die_msg} ]] && has stricter ${FEATURES} ; then
+ die "Aborting due to QA concerns: ${die_msg}"
+ fi
+
+ PORTAGE_QUIET=${tmp_quiet}
+ fi
+}
+
__dyn_instprep() {
if [[ -e ${PORTAGE_BUILDDIR}/.instprepped ]] ; then
__vecho ">>> It appears that '$PF' is already instprepped; skipping."
@@ -318,14 +742,267 @@ postinst_qa_check() {
done < <(printf "%s\0" "${qa_checks[@]}" | LC_ALL=C sort -u -z)
}
+install_mask() {
+ local root="$1"
+ shift
+ local install_mask="$*"
+
+ # We think of $install_mask as a space-separated list of
+ # globs. We don't want globbing in the "for" loop; that is, we
+ # want to keep the asterisks in the indivual entries.
+ local shopts=$-
+ set -o noglob
+ local no_inst
+ for no_inst in ${install_mask}; do
+ # Here, $no_inst is a single "entry" potentially
+ # containing a glob. From now on, we *do* want to
+ # expand it.
+ set +o noglob
+
+ # The standard case where $no_inst is something that
+ # the shell could expand on its own.
+ if [[ -e "${root}"/${no_inst} || -L "${root}"/${no_inst} ||
+ "${root}"/${no_inst} != $(echo "${root}"/${no_inst}) ]] ; then
+ __quiet_mode || einfo "Removing ${no_inst}"
+ rm -Rf "${root}"/${no_inst} >&/dev/null
+ fi
+
+ # We also want to allow the user to specify a "bare
+ # glob." For example, $no_inst="*.a" should prevent
+ # ALL files ending in ".a" from being installed,
+ # regardless of their location/depth. We achieve this
+ # by passing the pattern to `find`.
+ find "${root}" \( -path "${no_inst}" -or -name "${no_inst}" \) \
+ -print0 2> /dev/null \
+ | LC_ALL=C sort -z \
+ | while read -r -d ''; do
+ __quiet_mode || einfo "Removing /${REPLY#${root}}"
+ rm -Rf "${REPLY}" >&/dev/null
+ done
+
+ done
+ # set everything back the way we found it
+ set +o noglob
+ set -${shopts}
+}
+
+preinst_aix() {
+ if [[ ${CHOST} != *-aix* ]] || has binchecks ${RESTRICT}; then
+ return 0
+ fi
+ local ar strip
+ if type ${CHOST}-ar >/dev/null 2>&1 && type ${CHOST}-strip >/dev/null 2>&1; then
+ ar=${CHOST}-ar
+ strip=${CHOST}-strip
+ elif [[ ${CBUILD} == "${CHOST}" ]] && type ar >/dev/null 2>&1 && type strip >/dev/null 2>&1; then
+ ar=ar
+ strip=strip
+ elif [[ -x /usr/ccs/bin/ar && -x /usr/ccs/bin/strip ]]; then
+ ar=/usr/ccs/bin/ar
+ strip=/usr/ccs/bin/strip
+ else
+ die "cannot find where to use 'ar' and 'strip' from"
+ fi
+ local archives_members= archives=() helperfiles=()
+ local archive_member soname runpath needed archive contentmember
+ while read archive_member; do
+ archive_member=${archive_member#*;${EPREFIX}/} # drop "^type;EPREFIX/"
+ soname=${archive_member#*;}
+ runpath=${soname#*;}
+ needed=${runpath#*;}
+ soname=${soname%%;*}
+ runpath=${runpath%%;*}
+ archive_member=${archive_member%%;*} # drop ";soname;runpath;needed$"
+ archive=${archive_member%[*}
+ if [[ ${archive_member} != *'['*']' ]]; then
+ if [[ "${soname};${runpath};${needed}" == "${archive##*/};;" && -e ${EROOT}${archive} ]]; then
+ # most likely is an archive stub that already exists,
+ # may have to preserve members being a shared object.
+ archives[${#archives[@]}]=${archive}
+ fi
+ continue
+ fi
+ archives_members="${archives_members}:(${archive_member}):"
+ contentmember="${archive%/*}/.${archive##*/}${archive_member#${archive}}"
+ # portage does os.lstat() on merged files every now
+ # and then, so keep stamp-files for archive members
+ # around to get the preserve-libs feature working.
+ helperfiles[${#helperfiles[@]}]=${ED}${contentmember}
+ done < "${PORTAGE_BUILDDIR}"/build-info/NEEDED.XCOFF.1
+ if [[ ${#helperfiles[@]} > 0 ]]; then
+ rm -f "${helperfiles[@]}" || die "cannot prune ${helperfiles[@]}"
+ local f prev=
+ for f in "${helperfiles[@]}"
+ do
+ if [[ -z ${prev} ]]; then
+ { echo "Please leave this file alone, it is an important helper"
+ echo "for portage to implement the 'preserve-libs' feature on AIX."
+ } > "${f}" || die "cannot create ${f}"
+ chmod 0400 "${f}" || die "cannot chmod ${f}"
+ prev=${f}
+ else
+ ln "${prev}" "${f}" || die "cannot create hardlink ${f}"
+ fi
+ done
+ fi
+
+ local preservemembers libmetadir prunedirs=()
+ local FILE MEMBER FLAGS
+ for archive in "${archives[@]}"; do
+ preservemembers=
+ while read line; do
+ [[ -n ${line} ]] || continue
+ FILE= MEMBER= FLAGS=
+ eval ${line}
+ [[ ${FILE} == ${EROOT}${archive} ]] ||
+ die "invalid result of aixdll-query for ${EROOT}${archive}"
+ [[ -n ${MEMBER} && " ${FLAGS} " == *" SHROBJ "* ]] || continue
+ [[ ${archives_members} == *":(${archive}[${MEMBER}]):"* ]] && continue
+ preservemembers="${preservemembers} ${MEMBER}"
+ done <<-EOF
+ $(aixdll-query "${EROOT}${archive}" FILE MEMBER FLAGS)
+ EOF
+ [[ -n ${preservemembers} ]] || continue
+ einfo "preserving (on spec) ${archive}[${preservemembers# }]"
+ libmetadir=${ED}${archive%/*}/.${archive##*/}
+ mkdir "${libmetadir}" || die "cannot create ${libmetadir}"
+ pushd "${libmetadir}" >/dev/null || die "cannot cd to ${libmetadir}"
+ ${ar} -X32_64 -x "${EROOT}${archive}" ${preservemembers} || die "cannot unpack ${EROOT}${archive}"
+ chmod u+w ${preservemembers} || die "cannot chmod${preservemembers}"
+ ${strip} -X32_64 -e ${preservemembers} || die "cannot strip${preservemembers}"
+ ${ar} -X32_64 -q "${ED}${archive}" ${preservemembers} || die "cannot update ${archive}"
+ eend $?
+ popd >/dev/null || die "cannot leave ${libmetadir}"
+ prunedirs[${#prunedirs[@]}]=${libmetadir}
+ done
+ [[ ${#prunedirs[@]} == 0 ]] ||
+ rm -rf "${prunedirs[@]}" || die "cannot prune ${prunedirs[@]}"
+ return 0
+}
+
+postinst_aix() {
+ if [[ ${CHOST} != *-aix* ]] || has binchecks ${RESTRICT}; then
+ return 0
+ fi
+ local MY_PR=${PR%r0}
+ local ar strip
+ if type ${CHOST}-ar >/dev/null 2>&1 && type ${CHOST}-strip >/dev/null 2>&1; then
+ ar=${CHOST}-ar
+ strip=${CHOST}-strip
+ elif [[ ${CBUILD} == "${CHOST}" ]] && type ar >/dev/null 2>&1 && type strip >/dev/null 2>&1; then
+ ar=ar
+ strip=strip
+ elif [[ -x /usr/ccs/bin/ar && -x /usr/ccs/bin/strip ]]; then
+ ar=/usr/ccs/bin/ar
+ strip=/usr/ccs/bin/strip
+ else
+ die "cannot find where to use 'ar' and 'strip' from"
+ fi
+ local archives_members= archives=() activearchives=
+ local archive_member soname runpath needed
+ while read archive_member; do
+ archive_member=${archive_member#*;${EPREFIX}/} # drop "^type;EPREFIX/"
+ soname=${archive_member#*;}
+ runpath=${soname#*;}
+ needed=${runpath#*;}
+ soname=${soname%%;*}
+ runpath=${runpath%%;*}
+ archive_member=${archive_member%%;*} # drop ";soname;runpath;needed$"
+ [[ ${archive_member} == *'['*']' ]] && continue
+ [[ "${soname};${runpath};${needed}" == "${archive_member##*/};;" ]] || continue
+ # most likely is an archive stub, we might have to
+ # drop members being preserved shared objects.
+ archives[${#archives[@]}]=${archive_member}
+ activearchives="${activearchives}:(${archive_member}):"
+ done < "${PORTAGE_BUILDDIR}"/build-info/NEEDED.XCOFF.1
+
+ local type allcontentmembers= oldarchives=()
+ local contentmember
+ while read type contentmember; do
+ [[ ${type} == 'obj' ]] || continue
+ contentmember=${contentmember% *} # drop " timestamp$"
+ contentmember=${contentmember% *} # drop " hash$"
+ [[ ${contentmember##*/} == *'['*']' ]] || continue
+ contentmember=${contentmember#${EPREFIX}/}
+ allcontentmembers="${allcontentmembers}:(${contentmember}):"
+ contentmember=${contentmember%[*}
+ contentmember=${contentmember%/.*}/${contentmember##*/.}
+ [[ ${activearchives} == *":(${contentmember}):"* ]] && continue
+ oldarchives[${#oldarchives[@]}]=${contentmember}
+ done < "${EPREFIX}/var/db/pkg/${CATEGORY}/${P}${MY_PR:+-}${MY_PR}/CONTENTS"
+
+ local archive line delmembers
+ local FILE MEMBER FLAGS
+ for archive in "${archives[@]}"; do
+ [[ -r ${EROOT}${archive} && -w ${EROOT}${archive} ]] ||
+ chmod a+r,u+w "${EROOT}${archive}" || die "cannot chmod ${EROOT}${archive}"
+ delmembers=
+ while read line; do
+ [[ -n ${line} ]] || continue
+ FILE= MEMBER= FLAGS=
+ eval ${line}
+ [[ ${FILE} == "${EROOT}${archive}" ]] ||
+ die "invalid result '${FILE}' of aixdll-query, expected '${EROOT}${archive}'"
+ [[ -n ${MEMBER} && " ${FLAGS} " == *" SHROBJ "* ]] || continue
+ [[ ${allcontentmembers} == *":(${archive%/*}/.${archive##*/}[${MEMBER}]):"* ]] && continue
+ delmembers="${delmembers} ${MEMBER}"
+ done <<-EOF
+ $(aixdll-query "${EROOT}${archive}" FILE MEMBER FLAGS)
+ EOF
+ [[ -n ${delmembers} ]] || continue
+ einfo "dropping ${archive}[${delmembers# }]"
+ rm -f "${EROOT}${archive}".new || die "cannot prune ${EROOT}${archive}.new"
+ cp "${EROOT}${archive}" "${EROOT}${archive}".new || die "cannot backup ${archive}"
+ ${ar} -X32_64 -z -o -d "${EROOT}${archive}".new ${delmembers} || die "cannot remove${delmembers} from ${archive}.new"
+ mv -f "${EROOT}${archive}".new "${EROOT}${archive}" || die "cannot put ${EROOT}${archive} in place"
+ eend $?
+ done
+ local libmetadir keepmembers prunedirs=()
+ for archive in "${oldarchives[@]}"; do
+ [[ -r ${EROOT}${archive} && -w ${EROOT}${archive} ]] ||
+ chmod a+r,u+w "${EROOT}${archive}" || die "cannot chmod ${EROOT}${archive}"
+ keepmembers=
+ while read line; do
+ FILE= MEMBER= FLAGS=
+ eval ${line}
+ [[ ${FILE} == "${EROOT}${archive}" ]] ||
+ die "invalid result of aixdll-query for ${EROOT}${archive}"
+ [[ -n ${MEMBER} && " ${FLAGS} " == *" SHROBJ "* ]] || continue
+ [[ ${allcontentmembers} == *":(${archive%/*}/.${archive##*/}[${MEMBER}]):"* ]] || continue
+ keepmembers="${keepmembers} ${MEMBER}"
+ done <<-EOF
+ $(aixdll-query "${EROOT}${archive}" FILE MEMBER FLAGS)
+ EOF
+
+ if [[ -n ${keepmembers} ]]; then
+ einfo "preserving (extra)${keepmembers}"
+ libmetadir=${EROOT}${archive%/*}/.${archive##*/}
+ [[ ! -e ${libmetadir} ]] || rm -rf "${libmetadir}" || die "cannot prune ${libmetadir}"
+ mkdir "${libmetadir}" || die "cannot create ${libmetadir}"
+ pushd "${libmetadir}" >/dev/null || die "cannot cd to ${libmetadir}"
+ ${ar} -X32_64 -x "${EROOT}${archive}" ${keepmembers} || die "cannot unpack ${archive}"
+ ${strip} -X32_64 -e ${keepmembers} || die "cannot strip ${keepmembers}"
+ rm -f "${EROOT}${archive}.new" || die "cannot prune ${EROOT}${archive}.new"
+ ${ar} -X32_64 -q "${EROOT}${archive}.new" ${keepmembers} || die "cannot create ${EROOT}${archive}.new"
+ mv -f "${EROOT}${archive}.new" "${EROOT}${archive}" || die "cannot put ${EROOT}${archive} in place"
+ popd > /dev/null || die "cannot leave ${libmetadir}"
+ prunedirs[${#prunedirs[@]}]=${libmetadir}
+ eend $?
+ fi
+ done
+ [[ ${#prunedirs[@]} == 0 ]] ||
+ rm -rf "${prunedirs[@]}" || die "cannot prune ${prunedirs[@]}"
+ return 0
+}
+
preinst_mask() {
# Remove man pages, info pages, docs if requested. This is
# implemented in bash in order to respect INSTALL_MASK settings
# from bashrc.
local f x
for f in man info doc; do
- if has no${f} ${FEATURES}; then
- INSTALL_MASK+=" /usr/share/${f}"
+ if has no${f} $FEATURES; then
+ INSTALL_MASK="${INSTALL_MASK} ${EPREFIX}/usr/share/${f}"
fi
done
@@ -477,7 +1154,7 @@ __dyn_package() {
$PORTAGE_COMPRESSION_COMMAND > "$PORTAGE_BINPKG_TMPFILE"
assert "failed to pack binary package: '$PORTAGE_BINPKG_TMPFILE'"
PYTHONPATH=${PORTAGE_PYTHONPATH:-${PORTAGE_PYM_PATH}} \
- "${PORTAGE_PYTHON:-/usr/bin/python}" "$PORTAGE_BIN_PATH"/xpak-helper.py recompose \
+ "${PORTAGE_PYTHON:-@PREFIX_PORTAGE_PYTHON@}" "$PORTAGE_BIN_PATH"/xpak-helper.py recompose \
"$PORTAGE_BINPKG_TMPFILE" "$PORTAGE_BUILDDIR/build-info"
if [ $? -ne 0 ]; then
rm -f "${PORTAGE_BINPKG_TMPFILE}"
diff --git a/bin/phase-functions.sh b/bin/phase-functions.sh
index 90e622e75..78bb5caca 100644
--- a/bin/phase-functions.sh
+++ b/bin/phase-functions.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2019 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
@@ -31,7 +31,7 @@ PORTAGE_READONLY_VARS="D EBUILD EBUILD_PHASE EBUILD_PHASE_FUNC \
PORTAGE_TMPDIR PORTAGE_UPDATE_ENV PORTAGE_USERNAME \
PORTAGE_VERBOSE PORTAGE_WORKDIR_MODE PORTAGE_XATTR_EXCLUDE \
REPLACING_VERSIONS REPLACED_BY_VERSION T WORKDIR \
- __PORTAGE_HELPER __PORTAGE_TEST_HARDLINK_LOCKS"
+ __PORTAGE_HELPER __PORTAGE_TEST_HARDLINK_LOCKS ED EROOT"
PORTAGE_SAVED_READONLY_VARS="A CATEGORY P PF PN PR PV PVR"
@@ -146,7 +146,7 @@ __filter_readonly_variables() {
fi
fi
- "${PORTAGE_PYTHON:-/usr/bin/python}" "${PORTAGE_BIN_PATH}"/filter-bash-environment.py "${filtered_vars}" || die "filter-bash-environment.py failed"
+ "${PORTAGE_PYTHON:-@PREFIX_PORTAGE_PYTHON@}" "${PORTAGE_BIN_PATH}"/filter-bash-environment.py "${filtered_vars}" || die "filter-bash-environment.py failed"
}
# @FUNCTION: __preprocess_ebuild_env
@@ -763,6 +763,7 @@ __dyn_help() {
echo "production (stripped)"
fi
echo " merge to : ${ROOT}"
+ echo " offset : ${EPREFIX}"
echo
if [ -n "$USE" ]; then
echo "Additionally, support for the following optional features will be enabled:"
@@ -1087,7 +1088,7 @@ __ebuild_main() {
__save_ebuild_env | __filter_readonly_variables \
--filter-features > "$T/environment"
assert "__save_ebuild_env failed"
- chgrp "${PORTAGE_GRPNAME:-portage}" "$T/environment"
+ chgrp "${PORTAGE_GRPNAME:-${PORTAGE_GROUP}}" "$T/environment"
chmod g+w "$T/environment"
fi
[[ -n $PORTAGE_EBUILD_EXIT_FILE ]] && > "$PORTAGE_EBUILD_EXIT_FILE"
diff --git a/bin/phase-helpers.sh b/bin/phase-helpers.sh
index 9495465f9..c4ab51d78 100644
--- a/bin/phase-helpers.sh
+++ b/bin/phase-helpers.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
@@ -895,6 +895,22 @@ ___best_version_and_has_version_common() {
fi ;;
esac
+ # PREFIX LOCAL: stacked-prefix feature
+ if ___eapi_has_prefix_variables &&
+ has "${root_arg}" '--host-root' '-b' &&
+ has stacked-prefix ${FEATURES} &&
+ [[ -z ${ROOT%/} ]] &&
+ [[ ${CBUILD} == ${CHOST} ]] &&
+ [[ ${EPREFIX} != ${BROOT-${PORTAGE_OVERRIDE_EPREFIX}} ]] &&
+ :; then
+ # When we merge into another EPREFIX, but not into some ROOT,
+ # and CHOST is equal to CBUILD, build tools found in EPREFIX
+ # perfectly work for the current build environment.
+ # In a "stacked prefix" we explicitly utilize this situation.
+ "${FUNCNAME[1]}" "${atom}" && return 0
+ fi
+ # END PREFIX LOCAL
+
if [[ -n $PORTAGE_IPC_DAEMON ]] ; then
cmd+=("${PORTAGE_BIN_PATH}"/ebuild-ipc "${FUNCNAME[1]}" "${root}" "${atom}")
else
diff --git a/bin/portageq b/bin/portageq
index 3be5ab584..2d572b70c 100755
--- a/bin/portageq
+++ b/bin/portageq
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
@@ -28,8 +28,8 @@ if os.path.isfile(os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(
pym_paths = [os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "lib")]
sys.path.insert(0, pym_paths[0])
else:
- import distutils.sysconfig
- pym_paths = [os.path.join(distutils.sysconfig.get_python_lib(), x) for x in ("_emerge", "portage")]
+ pym_paths = [ os.path.join(os.path.dirname(
+ os.path.dirname(os.path.realpath(__file__))), "pym") ]
# Avoid sandbox violations after Python upgrade.
if os.environ.get("SANDBOX_ON") == "1":
sandbox_write = os.environ.get("SANDBOX_WRITE", "").split(":")
diff --git a/bin/quickpkg b/bin/quickpkg
index df8c1a8e8..b9ce52f8a 100755
--- a/bin/quickpkg
+++ b/bin/quickpkg
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/readpecoff b/bin/readpecoff
new file mode 100755
index 000000000..389b55081
--- /dev/null
+++ b/bin/readpecoff
@@ -0,0 +1,108 @@
+#!@PORTAGE_BASH@
+
+###################################################################
+# This script does the following: for implemented platforms, #
+# it echos for each given path a line with the following format: #
+# #
+# <arch>;<obj>;<soname>;<rpath1:rpathN>;<needed1,neededN> #
+# #
+# arch may be any string, e.g. "PE32". obj is the full (!) path #
+# to the file itself. soname, rpath and needed should be self #
+# explaining - rpath is ":" separated, needed is "," separated. #
+# #
+# WARNING: Depends on CHOST argument to decide what to do! #
+# #
+# WARNING: The Script does _never_ fail! If required binaries #
+# are missing, or information gathering fails, the #
+# script will SILENTLY (!) exit, to not disturb the #
+# normal merging process. #
+# #
+# WARNING: The _first_ argument needs to be a valid CHOST!!! #
+# #
+###################################################################
+
+
+# Interix: Uses native objdump, since thats the only facility that
+# knows about the native shared library information data.
+# objdump is there in all interix installations where the GNU SDK
+# is installed, which is a prerequisite for prefix anyway.
+
+scanbin_interix() {
+ local _itx_objdump="/opt/gcc.3.3/bin/objdump"
+ [[ -x ${_itx_objdump} ]] || _itx_objdump="/opt/gcc.4.2/bin/objdump"
+ [[ -x ${_itx_objdump} ]] || exit 0
+
+ # objdump is there, so now gather the information
+ _itx_full_info() {
+ local obj="$(cd "$(dirname "$1")"; pwd)/${1##*/}"
+ local so=
+ local rp=
+ local ne=
+
+ { file -L "${obj}" | grep "PE" > /dev/null 2>&1; } || return
+
+ _itx_gather() {
+ ${_itx_objdump} -p "$1" | while IFS= read line; do
+ [[ ${line} == *RPATH* || ${line} == *NEEDED* || ${line} == *SONAME* ]] || continue
+
+ eval "$(echo "${line}" | sed -e 's,[[:space:]]*\([A-Z]*\)[[:space:]]*\(.*\)$,key=\1;value="\2",g')"
+
+ case "${key}" in
+ RPATH) echo "rp=\"${value}\"" ;;
+ NEEDED) echo "test -n \"\${ne}\" && ne=\"\${ne},${value}\"; test -z \"\${ne}\" && ne=\"${value}\"" ;;
+ SONAME) echo "so=\"${value}\"" ;;
+ esac
+ done
+ }
+
+ eval "$(_itx_gather ${obj})"
+ echo "386;${obj};${so};${rp};${ne}"
+ }
+
+ for x in "$@"; do
+ _itx_full_info "${x}"
+ done
+
+ exit 0
+}
+
+
+# Native Windows: Uses the winnt compiler ("parity") to gather
+# information. parity is the only one knowing about the location
+# and format of the relevant data, and it is there always when
+# wanting to build native win32 executables.
+
+scanbin_winnt() {
+ local _winnt_inspector="$(type -P "parity.inspector")"
+ [[ -x ${_winnt_inspector} ]] || exit 0
+
+ _winnt_full_info () {
+ local obj="$(cd "$(dirname "$1")"; pwd)/${1##*/}"
+
+ { file -L "${obj}" | grep "PE" > /dev/null 2>&1; } || exit 0
+
+ # parity.inspector in --raw mode has exactly the format we
+ # want - wonder, wonder, i implemented that switch :)
+
+ local info="$(${_winnt_inspector} --raw "${obj}")"
+ echo "386;${obj};${info}"
+ }
+
+ for x in "$@"; do
+ _winnt_full_info "${x}"
+ done
+}
+
+# CHOST is the first argument!
+_chost=$1
+
+# verify CHOST...
+[[ -z ${_chost} ]] && { echo "CHOST not set!!"; exit 1; }
+[[ ${_chost} == *-*-* ]] || { echo "invalid CHOST!!"; exit 1; }
+shift
+
+case "${_chost}" in
+*-interix*) scanbin_interix "$@" ;;
+*-winnt*) scanbin_winnt "$@" ;;
+esac
+
diff --git a/bin/regenworld b/bin/regenworld
index bedc58bda..45394ab5b 100755
--- a/bin/regenworld
+++ b/bin/regenworld
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/save-ebuild-env.sh b/bin/save-ebuild-env.sh
index 947ac79d5..7d7235f23 100644..100755
--- a/bin/save-ebuild-env.sh
+++ b/bin/save-ebuild-env.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
@@ -89,9 +89,13 @@ __save_ebuild_env() {
___eapi_has_package_manager_build_user && unset -f package_manager_build_user
___eapi_has_package_manager_build_group && unset -f package_manager_build_group
- # Clear out the triple underscore namespace as it is reserved by the PM.
- unset -f $(compgen -A function ___)
- unset ${!___*}
+ # BEGIN PREFIX LOCAL: compgen is not compiled in during bootstrap
+ if type compgen >& /dev/null ; then
+ # Clear out the triple underscore namespace as it is reserved by the PM.
+ unset -f $(compgen -A function ___)
+ unset ${!___*}
+ fi
+ # END PREFIX LOCAL
# portage config variables and variables set directly by portage
unset ACCEPT_LICENSE BAD BRACKET BUILD_PREFIX COLS \
@@ -118,6 +122,10 @@ __save_ebuild_env() {
# user config variables
unset DOC_SYMLINKS_DIR INSTALL_MASK PKG_INSTALL_MASK
+ # PREFIX LOCAL: Prefix additions
+ unset EXTRA_PATH PORTAGE_GROUP PORTAGE_USER
+ # END PREFIX LOCAL
+
declare -p
declare -fp
if [[ ${BASH_VERSINFO[0]} == 3 ]]; then
diff --git a/bin/xattr-helper.py b/bin/xattr-helper.py
index 49c981580..a8aef3880 100755
--- a/bin/xattr-helper.py
+++ b/bin/xattr-helper.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 2012-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/bin/xpak-helper.py b/bin/xpak-helper.py
index 8c965ecda..ccb6c0eff 100755
--- a/bin/xpak-helper.py
+++ b/bin/xpak-helper.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python -b
+#!@PREFIX_PORTAGE_PYTHON@ -b
# Copyright 2009-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
diff --git a/cnf/Makefile.in b/cnf/Makefile.in
new file mode 100644
index 000000000..6cf3fc690
--- /dev/null
+++ b/cnf/Makefile.in
@@ -0,0 +1,42 @@
+SHELL = @PORTAGE_BASH@
+
+prefix = @prefix@
+sysconfdir = @sysconfdir@
+datadir = @datadir@
+
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+PORTAGE_CONF = $(datadir)/portage/config
+
+portageuser = @portageuser@
+portagegroup = @portagegroup@
+
+INSTALL = @INSTALL@
+INSTALL_subst = ${top_builddir}/subst-install
+LN_S = @LN_S@
+
+all:
+
+install:
+ $(INSTALL) -d -m 755 -o "$(portageuser)" -g "$(portagegroup)" $(DESTDIR)$(PORTAGE_CONF)
+ $(INSTALL_subst) \
+ -o "$(portageuser)" -g "$(portagegroup)" \
+ -t "$(DESTDIR)$(PORTAGE_CONF)" \
+ "$(srcdir)"/make.globals "$(srcdir)"/repos.conf
+ $(INSTALL) -d -m 755 -o "$(portageuser)" -g "$(portagegroup)" $(DESTDIR)$(PORTAGE_CONF)/sets
+ $(INSTALL_subst) \
+ -o "$(portageuser)" -g "$(portagegroup)" \
+ -t "$(DESTDIR)$(PORTAGE_CONF)/sets" \
+ "$(srcdir)"/sets/portage.conf
+ $(INSTALL_subst) \
+ -o "$(portageuser)" -g "$(portagegroup)" \
+ "$(srcdir)"/make.conf.example "$(DESTDIR)$(PORTAGE_CONF)"/make.conf.example
+ $(INSTALL) -d -m 755 -o "$(portageuser)" -g "$(portagegroup)" $(DESTDIR)$(sysconfdir)
+ $(INSTALL_subst) \
+ -o "$(portageuser)" -g "$(portagegroup)" \
+ -t "$(DESTDIR)$(sysconfdir)" \
+ "$(srcdir)"/dispatch-conf.conf \
+ "$(srcdir)"/etc-update.conf
+ ( cd $(DESTDIR)$(sysconfdir) && $(LN_S) $(DESTDIR)$(PORTAGE_CONF)/make.globals )
+
+.PHONY: all install
diff --git a/cnf/make.conf.example b/cnf/make.conf.example
index a309a5c43..c1d060c7c 100644
--- a/cnf/make.conf.example
+++ b/cnf/make.conf.example
@@ -100,7 +100,7 @@
# PORTAGE_TMPDIR is the location portage will use for compilations and
# temporary storage of data. This can get VERY large depending upon
# the application being installed.
-#PORTAGE_TMPDIR=/var/tmp
+#PORTAGE_TMPDIR=@PORTAGE_EPREFIX@/var/tmp
#
# PORTDIR is the location of the ebuild repository. This is the repository
# for all profile information as well as all ebuilds. If you change
@@ -108,7 +108,7 @@
# ***Warning***
# Data stored inside PORTDIR is in peril of being overwritten or deleted by
# the emerge --sync command.
-#PORTDIR=/var/db/repos/gentoo
+#PORTDIR=@PORTAGE_EPREFIX@/var/db/repos/gentoo
#
# DISTDIR is where all of the source code tarballs will be placed for
# emerges. After packages are built, it is safe to remove any and
@@ -116,12 +116,12 @@
# fetched on demand for a given build. If you would like to
# selectively prune obsolete files from this directory, see
# eclean from the gentoolkit package.
-#DISTDIR=/var/cache/distfiles
+#DISTDIR=@PORTAGE_EPREFIX@/var/cache/distfiles
#
# PKGDIR is the location of binary packages that you can have created
# with '--buildpkg' or '-b' while emerging a package. This can get
# up to several hundred megs, or even a few gigs.
-#PKGDIR=/var/cache/binpkgs
+#PKGDIR=@PORTAGE_EPREFIX@/var/cache/binpkgs
#
# PORTAGE_LOGDIR is the location where portage will store all the logs it
# creates from each individual merge. They are stored as
@@ -134,7 +134,7 @@
# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
# concern that they will be deleted by rsync updates. Default is not
# defined.
-#PORTDIR_OVERLAY=/usr/local/portage
+#PORTDIR_OVERLAY=@PORTAGE_EPREFIX@/usr/local/portage
# Fetching files
# ==============
@@ -157,8 +157,8 @@
#RESUMECOMMAND="wget -c -t 3 -T 60 --passive-ftp --limit-rate=200k -O \"\${DISTDIR}/\${FILE}\" \"\${URI}\""
#
# Lukemftp (BSD ftp):
-#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \"\${DISTDIR}/\${FILE}\" \"\${URI}\""
-#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \"\${DISTDIR}/\${FILE}\" \"\${URI}\""
+#FETCHCOMMAND="lukemftp -s -a -o \"\${DISTDIR}/\${FILE}\" \"\${URI}\""
+#RESUMECOMMAND="lukemftp -s -a -R -o \"\${DISTDIR}/\${FILE}\" \"\${URI}\""
#
# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
# The list is a space separated list which is read left to right. If you use
@@ -210,6 +210,10 @@
# Instructions for setting up a local rsync server are available here:
# https://wiki.gentoo.org/wiki/Local_Mirror
#
+# For Gentoo Prefix, use the following URL:
+#
+# Default: "rsync://rsync.prefix.bitzolder.nl/gentoo-portage-prefix
+#
#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
#
# PORTAGE_RSYNC_RETRIES sets the number of times portage will attempt to retrieve
diff --git a/cnf/make.globals b/cnf/make.globals
index dd3f28f70..d3ba98513 100644
--- a/cnf/make.globals
+++ b/cnf/make.globals
@@ -27,12 +27,12 @@ ACCEPT_PROPERTIES="*"
ACCEPT_RESTRICT="*"
# Miscellaneous paths
-DISTDIR="/var/cache/distfiles"
-PKGDIR="/var/cache/binpkgs"
-RPMDIR="/var/cache/rpm"
+DISTDIR="@PORTAGE_EPREFIX@/var/cache/distfiles"
+PKGDIR="@PORTAGE_EPREFIX@/var/cache/binpkgs"
+RPMDIR="@PORTAGE_EPREFIX@/var/cache/rpm"
# Temporary build directory
-PORTAGE_TMPDIR="/var/tmp"
+PORTAGE_TMPDIR="@PORTAGE_EPREFIX@/var/tmp"
# The compression used for binary packages. Defaults to zstd except for
# existing installs where bzip2 is used for backward compatibility.
@@ -71,6 +71,9 @@ FEATURES="assume-digests binpkg-docompress binpkg-dostrip binpkg-logs
COLLISION_IGNORE="/lib/modules/* *.py[co] *\$py.class"
UNINSTALL_IGNORE="/lib/modules/*"
+# Force EPREFIX, ED and EROOT to exist in all EAPIs, not just 3 and up
+FEATURES="${FEATURES} force-prefix"
+
# By default wait 5 secs before cleaning a package
CLEAN_DELAY="5"
@@ -108,12 +111,32 @@ PORTAGE_SYNC_STALE="30"
PORTAGE_LOGDIR_CLEAN="find \"\${PORTAGE_LOGDIR}\" -type f ! -name \"summary.log*\" -mtime +7 -delete"
# Minimal CONFIG_PROTECT
+# NOTE: in Prefix, these are NOT prefixed on purpose, because the
+# profiles define them too
CONFIG_PROTECT="/etc"
CONFIG_PROTECT_MASK="/etc/env.d"
# Disable auto-use
USE_ORDER="env:pkg:conf:defaults:pkginternal:features:repo:env.d"
+# PREFIX LOCAL: additional vars set during install
+# Default portage user/group
+PORTAGE_USER='@portageuser@'
+PORTAGE_GROUP='@portagegroup@'
+PORTAGE_ROOT_USER='@rootuser@'
+
+# Default ownership of installed files.
+PORTAGE_INST_UID="@rootuid@"
+PORTAGE_INST_GID="@rootgid@"
+
+# Any extra PATHs to add to the ebuild environment's PATH (if any)
+EXTRA_PATH="@EXTRA_PATH@"
+
+# The offset prefix this Portage was configured with (not used by
+# Portage itself)
+CONFIGURE_EPREFIX="@PORTAGE_EPREFIX@"
+# END PREFIX LOCAL
+
# Mode bits for ${WORKDIR} (see ebuild.5).
PORTAGE_WORKDIR_MODE="0700"
@@ -121,9 +144,9 @@ PORTAGE_WORKDIR_MODE="0700"
PORTAGE_ELOG_CLASSES="log warn error"
PORTAGE_ELOG_SYSTEM="save_summary:log,warn,error,qa echo"
-PORTAGE_ELOG_MAILURI="root"
+PORTAGE_ELOG_MAILURI="@rootuser@"
PORTAGE_ELOG_MAILSUBJECT="[portage] ebuild log for \${PACKAGE} on \${HOST}"
-PORTAGE_ELOG_MAILFROM="portage@localhost"
+PORTAGE_ELOG_MAILFROM="@portageuser@@localhost"
# Signing command used by repoman
PORTAGE_GPG_SIGNING_COMMAND="gpg --sign --digest-algo SHA256 --clearsign --yes --default-key \"\${PORTAGE_GPG_KEY}\" --homedir \"\${PORTAGE_GPG_DIR}\" \"\${FILE}\""
@@ -138,6 +161,20 @@ PORTAGE_XATTR_EXCLUDE="btrfs.* security.evm security.ima
security.selinux system.nfs4_acl user.apache_handler
user.Beagle.* user.dublincore.* user.mime_encoding user.xdg.*"
+# Writeable paths for Mac OS X seatbelt sandbox
+#
+# If path ends in a slash (/), access will recursively be allowed to directory
+# contents (using a regex), not the directory itself. Without a slash, access
+# to the directory or file itself will be allowed (using a literal), so it can
+# be created, removed and changed. If both is needed, the directory needs to be
+# given twice, once with and once without the slash. Obviously this only makes
+# sense for directories, not files.
+#
+# An empty value for either variable will disable all restrictions on the
+# corresponding operation.
+MACOSSANDBOX_PATHS="/dev/fd/ /private/tmp/ /private/var/tmp/ @@PORTAGE_BUILDDIR@@/ @@PORTAGE_ACTUAL_DISTDIR@@/"
+MACOSSANDBOX_PATHS_CONTENT_ONLY="/dev/null /dev/dtracehelper /dev/tty /private/var/run/syslog"
+
# *****************************
# ** DO NOT EDIT THIS FILE **
# ***************************************************
diff --git a/cnf/repos.conf b/cnf/repos.conf
index 6cb6e3b3c..77ffab3e9 100644
--- a/cnf/repos.conf
+++ b/cnf/repos.conf
@@ -1,10 +1,10 @@
[DEFAULT]
-main-repo = gentoo
+main-repo = gentoo_prefix
-[gentoo]
-location = /var/db/repos/gentoo
+[gentoo_prefix]
+location = @PORTAGE_EPREFIX@/var/db/repos/gentoo
sync-type = rsync
-sync-uri = rsync://rsync.gentoo.org/gentoo-portage
+sync-uri = rsync://rsync.prefix.bitzolder.nl/gentoo-portage-prefix
auto-sync = yes
sync-rsync-verify-jobs = 1
sync-rsync-verify-metamanifest = yes
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 000000000..9083824eb
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,135 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(portage-prefix, @version@, prefix@gentoo.org)
+
+AC_PREREQ([2.61])
+
+case "${prefix}" in
+ '') AC_MSG_ERROR([bad value ${prefix} for --prefix, must not be empty]) ;;
+ */) AC_MSG_ERROR([bad value ${prefix} for --prefix, must not end with '/']) ;;
+ /*|NONE) ;;
+ *) AC_MSG_ERROR([bad value ${prefix} for --prefix, must start with /]) ;;
+esac
+
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+
+AM_INIT_AUTOMAKE
+
+dnl Checks for programs.
+dnl store cflags prior, otherwise it's not propagated.
+if test "x$CFLAGS" != "x"
+then
+ CFLAGS=$CFLAGS
+fi
+
+AC_PREFIX_DEFAULT([/usr])
+
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_EGREP
+
+GENTOO_PATH_XCU_ID()
+GENTOO_PATH_PYTHON([2.7])
+
+AC_PATH_PROG(PORTAGE_RM, [rm], no)
+AC_PATH_PROG(PORTAGE_MV, [mv], no)
+AC_PATH_PROG(PORTAGE_BASENAME, [basename], no)
+AC_PATH_PROG(PORTAGE_DIRNAME, [dirname], no)
+dnl avoid bash internal variable messing up things here
+GENTOO_PATH_GNUPROG(PORTAGE_BASH, [bash])
+GENTOO_PATH_GNUPROG(PORTAGE_SED, [sed])
+GENTOO_PATH_GNUPROG(PORTAGE_WGET, [wget])
+GENTOO_PATH_GNUPROG(PORTAGE_FIND, [find])
+GENTOO_PATH_GNUPROG(PORTAGE_XARGS, [xargs])
+GENTOO_PATH_GNUPROG(PORTAGE_GREP, [grep])
+
+AC_ARG_WITH(portage-user,
+AC_HELP_STRING([--with-portage-user=myuser],[use user 'myuser' as portage owner (default portage)]),
+[case "${withval}" in
+ ""|yes) AC_MSG_ERROR(bad value ${withval} for --with-portage-user);;
+ *) portageuser="${withval}";;
+esac],
+[portageuser="portage"])
+
+AC_ARG_WITH(portage-group,
+AC_HELP_STRING([--with-portage-group=mygroup],[use group 'mygroup' as portage users group (default portage)]),
+[case "${withval}" in
+ ""|yes) AC_MSG_ERROR(bad value ${withval} for --with-portage-group);;
+ *) portagegroup="${withval}";;
+esac],
+[portagegroup="portage"])
+
+AC_ARG_WITH(root-user,
+AC_HELP_STRING([--with-root-user=myuser],[uses 'myuser' as owner of installed files (default is portage-user)]),
+[case "${withval}" in
+ ""|yes) AC_MSG_ERROR(bad value ${withval} for --with-root-user);;
+ *) rootuser="${withval}";;
+esac],
+[rootuser="${portageuser}"])
+
+AC_MSG_CHECKING([for user id of ${rootuser}])
+dnl grab uid of rootuser
+rootuid=`${XCU_ID} -u "${rootuser}"`
+if test "x`echo ${rootuid} | ${EGREP} '^[[0-9]]+$'`" != "x"
+then
+ AC_MSG_RESULT([${rootuid}])
+else
+ AC_MSG_ERROR([error finding the user id of ${rootuser}])
+fi
+AC_MSG_CHECKING([for group id of ${rootuser}])
+rootgid=`${XCU_ID} -g "${rootuser}"`
+if test "x`echo ${rootgid} | ${EGREP} '^[[0-9]]+$'`" != "x"
+then
+ AC_MSG_RESULT([${rootgid}])
+else
+ AC_MSG_ERROR([error finding the group id of ${rootuser}])
+fi
+
+AC_ARG_WITH(offset-prefix,
+AC_HELP_STRING([--with-offset-prefix],
+ [specify the installation prefix for all packages, defaults to an empty string]),
+ [PORTAGE_EPREFIX=$withval],
+ [PORTAGE_EPREFIX=''])
+
+if test "x$PORTAGE_EPREFIX" != "x"
+then
+ PORTAGE_EPREFIX=`${PREFIX_PORTAGE_PYTHON} -c "import os; print(os.path.normpath('$PORTAGE_EPREFIX'))"`
+fi
+
+AC_ARG_WITH(extra-path,
+AC_HELP_STRING([--with-extra-path], [specify additional PATHs available to the portage build environment (use with care)]),
+[EXTRA_PATH="$withval"],
+[EXTRA_PATH=""])
+
+AC_SUBST(portageuser)
+AC_SUBST(portagegroup)
+AC_SUBST(rootuser)
+AC_SUBST(rootuid)
+AC_SUBST(rootgid)
+AC_SUBST(PORTAGE_EPREFIX)
+AC_SUBST(EXTRA_PATH)
+AC_SUBST(PORTAGE_BASE,['${exec_prefix}/lib/portage'])
+
+AC_SUBST(PORTAGE_RM)
+AC_SUBST(PORTAGE_MV)
+AC_SUBST(PORTAGE_BASENAME)
+AC_SUBST(PORTAGE_DIRNAME)
+AC_SUBST(PORTAGE_BASH)
+AC_SUBST(PORTAGE_SED)
+AC_SUBST(PORTAGE_WGET)
+AC_SUBST(PORTAGE_FIND)
+AC_SUBST(PORTAGE_XARGS)
+AC_SUBST(PORTAGE_GREP)
+
+AC_CONFIG_FILES([subst-install], [chmod +x subst-install])
+AC_CONFIG_FILES([
+ Makefile
+ man/Makefile
+ bin/Makefile
+ lib/Makefile
+ cnf/Makefile
+])
+
+AC_OUTPUT
diff --git a/lib/Makefile.in b/lib/Makefile.in
new file mode 100644
index 000000000..7d4193cc9
--- /dev/null
+++ b/lib/Makefile.in
@@ -0,0 +1,41 @@
+SHELL = @PORTAGE_BASH@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+sysconfdir = @sysconfdir@
+libdir = @libdir@
+PYTHON = @PREFIX_PORTAGE_PYTHON@
+
+srcdir=@srcdir@
+top_builddir=@top_builddir@
+
+portageuser = @portageuser@
+portagegroup = @portagegroup@
+
+PORTAGE_PYM = @PORTAGE_BASE@/lib
+INSTALL = @INSTALL@
+INSTALL_subst = ${top_builddir}/subst-install
+
+all:
+
+install:
+ $(INSTALL) -d -m 755 -o "$(portageuser)" -g "$(portagegroup)" $(DESTDIR)$(PORTAGE_PYM)
+ ( cd "$(srcdir)" && find * -type d ) | while read f ; do \
+ files=( ) ; \
+ shopt -s nullglob ; \
+ for t in "$(srcdir)/$${f}"/* ; do \
+ [[ -d $${t} ]] && continue ; \
+ [[ $${t} == */Makefile* ]] && continue ; \
+ files=( "$${files[@]}" "$${t}" ) ; \
+ done ; \
+ $(INSTALL) -d -m 755 \
+ -o "$(portageuser)" -g "$(portagegroup)" \
+ "$(DESTDIR)$(PORTAGE_PYM)/$${f}" && \
+ [[ $${files[0]} ]] || continue ; \
+ $(INSTALL_subst) \
+ -o "$(portageuser)" -g "$(portagegroup)" \
+ -t "$(DESTDIR)$(PORTAGE_PYM)/$${f}" \
+ "$${files[@]}" \
+ ; done
+
+.PHONY: all install
diff --git a/lib/_emerge/Package.py b/lib/_emerge/Package.py
index 3d7df2437..b2dfc07c1 100644
--- a/lib/_emerge/Package.py
+++ b/lib/_emerge/Package.py
@@ -48,7 +48,7 @@ class Package(Task):
"LICENSE", "MD5", "PDEPEND", "PROVIDES",
"RDEPEND", "repository", "REQUIRED_USE",
"PROPERTIES", "REQUIRES", "RESTRICT", "SIZE",
- "SLOT", "USE", "_mtime_"]
+ "SLOT", "USE", "_mtime_", "EPREFIX"]
_dep_keys = ('BDEPEND', 'DEPEND', 'PDEPEND', 'RDEPEND')
_buildtime_keys = ('BDEPEND', 'DEPEND')
diff --git a/lib/_emerge/actions.py b/lib/_emerge/actions.py
index 392f98d4d..d8e9d7774 100644
--- a/lib/_emerge/actions.py
+++ b/lib/_emerge/actions.py
@@ -40,6 +40,7 @@ from portage import os
from portage import shutil
from portage import eapi_is_supported, _encodings, _unicode_decode
from portage.cache.cache_errors import CacheError
+from portage.const import EPREFIX
from portage.const import GLOBAL_CONFIG_PATH, VCS_DIRS, _DEPCLEAN_LIB_CHECK_DEFAULT
from portage.const import SUPPORTED_BINPKG_FORMATS, TIMESTAMP_FORMAT
from portage.dbapi.dep_expand import dep_expand
@@ -2533,12 +2534,23 @@ def getgccversion(chost=None):
gcc_ver_command = ['gcc', '-dumpversion']
gcc_ver_prefix = 'gcc-'
+ clang_ver_command = ['clang', '--version']
+ clang_ver_prefix = 'clang-'
+
+ ubinpath = os.path.join('/', portage.const.EPREFIX, 'usr', 'bin')
+
gcc_not_found_error = red(
"!!! No gcc found. You probably need to 'source /etc/profile'\n" +
"!!! to update the environment of this terminal and possibly\n" +
"!!! other terminals also.\n"
)
+ def getclangversion(output):
+ version = re.search('clang version ([0-9.]+) ', output)
+ if version:
+ return version.group(1)
+ return "unknown"
+
if chost:
try:
proc = subprocess.Popen(["gcc-config", "-c"],
@@ -2566,7 +2578,7 @@ def getgccversion(chost=None):
return gcc_ver_prefix + myoutput
try:
- proc = subprocess.Popen(gcc_ver_command,
+ proc = subprocess.Popen([ubinpath + "/" + gcc_ver_command[0]] + gcc_ver_command[1:],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except OSError:
myoutput = None
@@ -2577,6 +2589,32 @@ def getgccversion(chost=None):
if mystatus == os.EX_OK:
return gcc_ver_prefix + myoutput
+ if chost:
+ try:
+ proc = subprocess.Popen(
+ [ubinpath + "/" + chost + "-" + clang_ver_command[0]] + clang_ver_command[1:],
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ except OSError:
+ myoutput = None
+ mystatus = 1
+ else:
+ myoutput = _unicode_decode(proc.communicate()[0]).rstrip("\n")
+ mystatus = proc.wait()
+ if mystatus == os.EX_OK:
+ return clang_ver_prefix + getclangversion(myoutput)
+
+ try:
+ proc = subprocess.Popen([ubinpath + "/" + clang_ver_command[0]] + clang_ver_command[1:],
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ except OSError:
+ myoutput = None
+ mystatus = 1
+ else:
+ myoutput = _unicode_decode(proc.communicate()[0]).rstrip("\n")
+ mystatus = proc.wait()
+ if mystatus == os.EX_OK:
+ return clang_ver_prefix + getclangversion(myoutput)
+
portage.writemsg(gcc_not_found_error, noiselevel=-1)
return "[unavailable]"
diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index ec90e59df..13c2b658f 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -10209,6 +10209,16 @@ def _get_masking_status(pkg, pkgsettings, root_config, myrepo=None, use=None):
mreasons.append(_MaskReason("CHOST", "CHOST: %s" % \
pkg._metadata["CHOST"]))
+ eprefix = pkgsettings["EPREFIX"]
+ if len(eprefix.rstrip('/')) > 0 and pkg.built and not pkg.installed:
+ if not "EPREFIX" in pkg._metadata:
+ mreasons.append(_MaskReason("EPREFIX",
+ "missing EPREFIX"))
+ elif len(pkg._metadata["EPREFIX"].strip()) < len(eprefix):
+ mreasons.append(_MaskReason("EPREFIX",
+ "EPREFIX: '%s' too small" % \
+ pkg._metadata["EPREFIX"]))
+
if pkg.invalid:
for msgs in pkg.invalid.values():
for msg in msgs:
diff --git a/lib/_emerge/emergelog.py b/lib/_emerge/emergelog.py
index cba98f395..cb7bf77b3 100644
--- a/lib/_emerge/emergelog.py
+++ b/lib/_emerge/emergelog.py
@@ -13,12 +13,13 @@ from portage import _unicode_decode
from portage import _unicode_encode
from portage.data import secpass
from portage.output import xtermTitle
+from portage.const import EPREFIX
# We disable emergelog by default, since it's called from
# dblink.merge() and we don't want that to trigger log writes
# unless it's really called via emerge.
_disable = True
-_emerge_log_dir = '/var/log'
+_emerge_log_dir = EPREFIX + '/var/log'
def emergelog(xterm_titles, mystr, short_msg=None):
diff --git a/lib/_emerge/getloadavg.py b/lib/_emerge/getloadavg.py
index 6a2794fb1..e4cb009cb 100644
--- a/lib/_emerge/getloadavg.py
+++ b/lib/_emerge/getloadavg.py
@@ -2,6 +2,7 @@
# Distributed under the terms of the GNU General Public License v2
from portage import os
+import platform
getloadavg = getattr(os, "getloadavg", None)
if getloadavg is None:
@@ -11,9 +12,17 @@ if getloadavg is None:
Raises OSError if the load average was unobtainable.
"""
try:
- with open('/proc/loadavg') as f:
- loadavg_str = f.readline()
- except IOError:
+ if platform.system() in ["AIX", "HP-UX"]:
+ loadavg_str = os.popen('LANG=C /usr/bin/uptime 2>/dev/null').readline().split()
+ while loadavg_str[0] != 'load' and loadavg_str[1] != 'average:':
+ loadavg_str = loadavg_str[1:]
+ loadavg_str = loadavg_str[2:5]
+ loadavg_str = [x.rstrip(',') for x in loadavg_str]
+ loadavg_str = ' '.join(loadavg_str)
+ else:
+ with open('/proc/loadavg') as f:
+ loadavg_str = f.readline()
+ except (IOError, IndexError):
# getloadavg() is only supposed to raise OSError, so convert
raise OSError('unknown')
loadavg_split = loadavg_str.split()
diff --git a/lib/portage/__init__.py b/lib/portage/__init__.py
index 60dbea693..ec667e478 100644
--- a/lib/portage/__init__.py
+++ b/lib/portage/__init__.py
@@ -122,7 +122,8 @@ try:
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
+ INCREMENTALS, EAPI, MISC_SH_BINARY, REPO_NAME_LOC, REPO_NAME_FILE, \
+ EPREFIX, rootuid
except ImportError as e:
sys.stderr.write("\n\n")
diff --git a/lib/portage/const.py b/lib/portage/const.py
index f6be9258f..146808fea 100644
--- a/lib/portage/const.py
+++ b/lib/portage/const.py
@@ -4,6 +4,11 @@
from __future__ import unicode_literals
+# ===========================================================================
+# autotool supplied constants.
+# ===========================================================================
+from portage.const_autotool import *
+
import os
# ===========================================================================
@@ -58,20 +63,33 @@ DEPCACHE_PATH = "/var/cache/edb/dep"
GLOBAL_CONFIG_PATH = "/usr/share/portage/config"
# these variables are not used with target_root or config_root
+PORTAGE_BASE_PATH = PORTAGE_BASE
# NOTE: Use realpath(__file__) so that python module symlinks in site-packages
# are followed back to the real location of the whole portage installation.
+#PREFIX: below should work, but I'm not sure how it it affects other places
# NOTE: Please keep PORTAGE_BASE_PATH in one line to help substitutions.
-PORTAGE_BASE_PATH = os.path.join(os.sep, os.sep.join(os.path.realpath(__file__.rstrip("co")).split(os.sep)[:-3]))
+#PORTAGE_BASE_PATH = os.path.join(os.sep, os.sep.join(os.path.realpath(__file__.rstrip("co")).split(os.sep)[:-3]))
PORTAGE_BIN_PATH = PORTAGE_BASE_PATH + "/bin"
PORTAGE_PYM_PATH = os.path.realpath(os.path.join(__file__, '../..'))
LOCALE_DATA_PATH = PORTAGE_BASE_PATH + "/locale" # FIXME: not used
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"
+SANDBOX_BINARY = EPREFIX + "/usr/bin/sandbox"
+FAKEROOT_BINARY = EPREFIX + "/usr/bin/fakeroot"
+BASH_BINARY = PORTAGE_BASH
+MOVE_BINARY = PORTAGE_MV
PRELINK_BINARY = "/usr/sbin/prelink"
+MACOSSANDBOX_BINARY = "/usr/bin/sandbox-exec"
+MACOSSANDBOX_PROFILE = '''(version 1)
+(allow default)
+(deny file-write*)
+(allow file-write* file-write-setugid
+@@MACOSSANDBOX_PATHS@@)
+(allow file-write-data
+@@MACOSSANDBOX_PATHS_CONTENT_ONLY@@)'''
+
+PORTAGE_GROUPNAME = portagegroup
+PORTAGE_USERNAME = portageuser
INVALID_ENV_FILE = "/etc/spork/is/not/valid/profile.env"
MERGING_IDENTIFIER = "-MERGING-"
@@ -190,6 +208,7 @@ SUPPORTED_FEATURES = frozenset([
"splitdebug",
"split-elog",
"split-log",
+ "stacked-prefix", # PREFIX LOCAL
"strict",
"strict-keepdir",
"stricter",
@@ -224,7 +243,9 @@ MANIFEST2_IDENTIFIERS = ("AUX", "MISC", "DIST", "EBUILD")
# a config instance (since it's possible to contruct a config instance with
# a different EPREFIX). Therefore, the EPREFIX constant should *NOT* be used
# in the definition of any other constants within this file.
-EPREFIX = ""
+# PREFIX LOCAL: rely on EPREFIX from autotools
+#EPREFIX = ""
+# END PREFIX LOCAL
# pick up EPREFIX from the environment if set
if "PORTAGE_OVERRIDE_EPREFIX" in os.environ:
diff --git a/lib/portage/const_autotool.py b/lib/portage/const_autotool.py
new file mode 100644
index 000000000..ee540319c
--- /dev/null
+++ b/lib/portage/const_autotool.py
@@ -0,0 +1,21 @@
+# Copyright: 2005-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+# all vars that are to wind up in portage_const must have their name listed in __all__
+
+__all__ = ["EPREFIX", "SYSCONFDIR", "PORTAGE_BASE",
+ "portageuser", "portagegroup", "rootuser", "rootuid", "rootgid",
+ "PORTAGE_BASH", "PORTAGE_MV"]
+
+EPREFIX = "@PORTAGE_EPREFIX@"
+SYSCONFDIR = "@sysconfdir@"
+PORTAGE_BASE = "@PORTAGE_BASE@"
+
+portagegroup = "@portagegroup@"
+portageuser = "@portageuser@"
+rootuser = "@rootuser@"
+rootuid = @rootuid@
+rootgid = @rootgid@
+
+PORTAGE_BASH = "@PORTAGE_BASH@"
+PORTAGE_MV = "@PORTAGE_MV@"
diff --git a/lib/portage/data.py b/lib/portage/data.py
index f9d67fc3d..20a8d1ba7 100644
--- a/lib/portage/data.py
+++ b/lib/portage/data.py
@@ -3,6 +3,7 @@
# Distributed under the terms of the GNU General Public License v2
import os, pwd, grp, platform, sys
+from portage.const import PORTAGE_GROUPNAME, PORTAGE_USERNAME, EPREFIX
import portage
portage.proxy.lazyimport.lazyimport(globals(),
@@ -15,7 +16,10 @@ from portage.localization import _
ostype = platform.system()
userland = None
-if ostype == "DragonFly" or ostype.endswith("BSD"):
+# Prefix always has USERLAND=GNU, even on
+# FreeBSD, OpenBSD and Darwin (thank the lord!).
+# Hopefully this entire USERLAND hack can go once
+if EPREFIX == "" and (ostype == "DragonFly" or ostype.endswith("BSD")):
userland = "BSD"
else:
userland = "GNU"
@@ -147,32 +151,44 @@ def _get_global(k):
#Discover the uid and gid of the portage user/group
keyerror = False
try:
- portage_uid = pwd.getpwnam(_get_global('_portage_username')).pw_uid
+ username = str(_get_global('_portage_username'))
+ portage_uid = pwd.getpwnam(username).pw_uid
except KeyError:
- keyerror = True
- portage_uid = 0
+ # PREFIX LOCAL: some sysadmins are insane, bug #344307
+ if username.isdigit():
+ portage_uid = int(username)
+ else:
+ keyerror = True
+ portage_uid = 0
+ # END PREFIX LOCAL
try:
- portage_gid = grp.getgrnam(_get_global('_portage_grpname')).gr_gid
+ grpname = str(_get_global('_portage_grpname'))
+ portage_gid = grp.getgrnam(grpname).gr_gid
except KeyError:
- keyerror = True
- portage_gid = 0
+ # PREFIX LOCAL: some sysadmins are insane, bug #344307
+ if grpname.isdigit():
+ portage_gid = int(grpname)
+ else:
+ keyerror = True
+ portage_gid = 0
+ # END PREFIX LOCAL
# Suppress this error message if both PORTAGE_GRPNAME and
# PORTAGE_USERNAME are set to "root", for things like
# Android (see bug #454060).
if keyerror and not (_get_global('_portage_username') == "root" and
_get_global('_portage_grpname') == "root"):
+ # PREFIX LOCAL: we need to fix this one day to distinguish prefix vs non-prefix
+ writemsg(colorize("BAD",
+ _("portage: '%s' user or '%s' group missing." % (_get_global('_portage_username'), _get_global('_portage_grpname')))) + "\n", noiselevel=-1)
writemsg(colorize("BAD",
- _("portage: 'portage' user or group missing.")) + "\n", noiselevel=-1)
- writemsg(_(
- " For the defaults, line 1 goes into passwd, "
- "and 2 into group.\n"), noiselevel=-1)
- writemsg(colorize("GOOD",
- " portage:x:250:250:portage:/var/tmp/portage:/bin/false") \
- + "\n", noiselevel=-1)
- writemsg(colorize("GOOD", " portage::250:portage") + "\n",
- noiselevel=-1)
+ _(" In Prefix Portage this is quite dramatic")) + "\n", noiselevel=-1)
+ writemsg(colorize("BAD",
+ _(" since it means you have thrown away yourself.")) + "\n", noiselevel=-1)
+ writemsg(colorize("BAD",
+ _(" Re-add yourself or re-bootstrap Gentoo Prefix.")) + "\n", noiselevel=-1)
+ # END PREFIX LOCAL
portage_group_warning()
globals()['portage_gid'] = portage_gid
@@ -251,7 +267,12 @@ def _get_global(k):
v = pwd_struct.pw_name
if v is None:
- v = 'portage'
+ # PREFIX LOCAL: use var iso hardwired 'portage'
+ if k == '_portage_grpname':
+ v = PORTAGE_GROUPNAME
+ else:
+ v = PORTAGE_USERNAME
+ # END PREFIX LOCAL
else:
raise AssertionError('unknown name: %s' % k)
@@ -288,13 +309,17 @@ def _init(settings):
# from grp.getgrnam() with PyPy
native_string = platform.python_implementation() == 'PyPy'
- v = settings.get('PORTAGE_GRPNAME', 'portage')
+ # PREFIX LOCAL: use var iso hardwired 'portage'
+ v = settings.get('PORTAGE_GRPNAME', PORTAGE_GROUPNAME)
+ # END PREFIX LOCAL
if native_string:
v = portage._native_string(v)
globals()['_portage_grpname'] = v
_initialized_globals.add('_portage_grpname')
- v = settings.get('PORTAGE_USERNAME', 'portage')
+ # PREFIX LOCAL: use var iso hardwired 'portage'
+ v = settings.get('PORTAGE_USERNAME', PORTAGE_USERNAME)
+ # END PREFIX LOCAL
if native_string:
v = portage._native_string(v)
globals()['_portage_username'] = v
diff --git a/lib/portage/dbapi/bintree.py b/lib/portage/dbapi/bintree.py
index 311c9a78a..2f6c4f343 100644
--- a/lib/portage/dbapi/bintree.py
+++ b/lib/portage/dbapi/bintree.py
@@ -97,7 +97,7 @@ class bindbapi(fakedbapi):
"DEPEND", "EAPI", "IUSE", "KEYWORDS",
"LICENSE", "MD5", "PDEPEND", "PROPERTIES",
"PROVIDES", "RDEPEND", "repository", "REQUIRES", "RESTRICT",
- "SIZE", "SLOT", "USE", "_mtime_"
+ "SIZE", "SLOT", "USE", "_mtime_", "EPREFIX"
])
self._aux_cache_slot_dict = slot_dict_class(self._aux_cache_keys)
self._aux_cache = {}
@@ -397,7 +397,7 @@ class binarytree(object):
"IUSE", "KEYWORDS", "LICENSE", "PDEPEND",
"PKGINDEX_URI", "PROPERTIES", "PROVIDES",
"RDEPEND", "repository", "REQUIRES", "RESTRICT",
- "SIZE", "SLOT", "USE"]
+ "SIZE", "SLOT", "USE", "EPREFIX"]
self._pkgindex_aux_keys = list(self._pkgindex_aux_keys)
self._pkgindex_use_evaluated_keys = \
("BDEPEND", "DEPEND", "LICENSE", "RDEPEND",
@@ -409,7 +409,8 @@ class binarytree(object):
"CONFIG_PROTECT", "CONFIG_PROTECT_MASK", "FEATURES",
"GENTOO_MIRRORS", "INSTALL_MASK", "IUSE_IMPLICIT", "USE",
"USE_EXPAND", "USE_EXPAND_HIDDEN", "USE_EXPAND_IMPLICIT",
- "USE_EXPAND_UNPREFIXED"])
+ "USE_EXPAND_UNPREFIXED",
+ "EPREFIX"])
self._pkgindex_default_pkg_data = {
"BDEPEND" : "",
"BUILD_ID" : "",
@@ -430,7 +431,7 @@ class binarytree(object):
"SLOT" : "0",
"USE" : "",
}
- self._pkgindex_inherited_keys = ["CHOST", "repository"]
+ self._pkgindex_inherited_keys = ["CHOST", "repository", "EPREFIX"]
# Populate the header with appropriate defaults.
self._pkgindex_default_header_data = {
diff --git a/lib/portage/dbapi/vartree.py b/lib/portage/dbapi/vartree.py
index 3687b471b..d7c8ef3de 100644
--- a/lib/portage/dbapi/vartree.py
+++ b/lib/portage/dbapi/vartree.py
@@ -42,6 +42,9 @@ portage.proxy.lazyimport.lazyimport(globals(),
'portage.util._xattr:xattr',
'portage.util._dyn_libs.PreservedLibsRegistry:PreservedLibsRegistry',
'portage.util._dyn_libs.LinkageMapELF:LinkageMapELF@LinkageMap',
+ 'portage.util._dyn_libs.LinkageMapMachO:LinkageMapMachO',
+ 'portage.util._dyn_libs.LinkageMapPeCoff:LinkageMapPeCoff',
+ 'portage.util._dyn_libs.LinkageMapXCoff:LinkageMapXCoff',
'portage.util._dyn_libs.NeededEntry:NeededEntry',
'portage.util._async.SchedulerInterface:SchedulerInterface',
'portage.util._eventloop.EventLoop:EventLoop',
@@ -53,7 +56,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
)
from portage.const import CACHE_PATH, CONFIG_MEMORY_FILE, \
- MERGING_IDENTIFIER, PORTAGE_PACKAGE_ATOM, PRIVATE_PATH, VDB_PATH
+ MERGING_IDENTIFIER, PORTAGE_PACKAGE_ATOM, PRIVATE_PATH, VDB_PATH, EPREFIX
from portage.dbapi import dbapi
from portage.exception import CommandNotFound, \
InvalidData, InvalidLocation, InvalidPackageName, \
@@ -205,6 +208,17 @@ class vardbapi(dbapi):
self._plib_registry = PreservedLibsRegistry(settings["ROOT"],
os.path.join(self._eroot, PRIVATE_PATH, "preserved_libs_registry"))
self._linkmap = LinkageMap(self)
+ chost = self.settings.get('CHOST')
+ if not chost:
+ chost = 'lunix?' # this happens when profiles are not available
+ if chost.find('darwin') >= 0:
+ self._linkmap = LinkageMapMachO(self)
+ elif chost.find('interix') >= 0 or chost.find('winnt') >= 0:
+ self._linkmap = LinkageMapPeCoff(self)
+ elif chost.find('aix') >= 0:
+ self._linkmap = LinkageMapXCoff(self)
+ else:
+ self._linkmap = LinkageMap(self)
self._owners = self._owners_db(self)
self._cached_counter = None
@@ -3255,7 +3269,7 @@ class dblink(object):
def path_to_node(path):
node = path_node_map.get(path)
if node is None:
- node = LinkageMap._LibGraphNode(linkmap._obj_key(path))
+ node = linkmap._LibGraphNode(linkmap._obj_key(path))
alt_path_node = lib_graph.get(node)
if alt_path_node is not None:
node = alt_path_node
@@ -3432,7 +3446,15 @@ class dblink(object):
def path_to_node(path):
node = path_node_map.get(path)
if node is None:
- node = LinkageMap._LibGraphNode(linkmap._obj_key(path))
+ chost = self.settings.get('CHOST')
+ if chost.find('darwin') >= 0:
+ node = LinkageMapMachO._LibGraphNode(linkmap._obj_key(path))
+ elif chost.find('interix') >= 0 or chost.find('winnt') >= 0:
+ node = LinkageMapPeCoff._LibGraphNode(linkmap._obj_key(path))
+ elif chost.find('aix') >= 0:
+ node = LinkageMapXCoff._LibGraphNode(linkmap._obj_key(path))
+ else:
+ node = LinkageMap._LibGraphNode(linkmap._obj_key(path))
alt_path_node = lib_graph.get(node)
if alt_path_node is not None:
node = alt_path_node
diff --git a/lib/portage/getbinpkg.py b/lib/portage/getbinpkg.py
index 14dc149b1..997cd2eab 100644
--- a/lib/portage/getbinpkg.py
+++ b/lib/portage/getbinpkg.py
@@ -20,6 +20,7 @@ import socket
import time
import tempfile
import base64
+from portage.const import CACHE_PATH
import warnings
_all_errors = [NotImplementedError, ValueError, socket.error]
@@ -587,11 +588,11 @@ def dir_get_metadata(baseurl, conn=None, chunk_size=3000, verbose=1, usingcache=
else:
keepconnection = 1
- cache_path = "/var/cache/edb"
+ cache_path = CACHE_PATH
metadatafilename = os.path.join(cache_path, 'remote_metadata.pickle')
if makepickle is None:
- makepickle = "/var/cache/edb/metadata.idx.most_recent"
+ makepickle = CACHE_PATH+"/metadata.idx.most_recent"
try:
conn = create_conn(baseurl, conn)[0]
diff --git a/lib/portage/package/ebuild/_config/special_env_vars.py b/lib/portage/package/ebuild/_config/special_env_vars.py
index 440dd00b2..12d701c9a 100644
--- a/lib/portage/package/ebuild/_config/special_env_vars.py
+++ b/lib/portage/package/ebuild/_config/special_env_vars.py
@@ -81,6 +81,9 @@ environ_whitelist += [
"ROOT", "ROOTPATH", "SANDBOX_LOG", "SYSROOT", "T", "TMP", "TMPDIR",
"USE_EXPAND", "USE_ORDER", "WORKDIR",
"XARGS", "__PORTAGE_TEST_HARDLINK_LOCKS",
+ # PREFIX LOCAL
+ "EXTRA_PATH", "PORTAGE_GROUP", "PORTAGE_USER",
+ # END PREFIX LOCAL
]
# user config variables
@@ -113,11 +116,13 @@ environ_whitelist += [
]
# other variables inherited from the calling environment
+# UNIXMODE is necessary for MiNT
environ_whitelist += [
"CVS_RSH", "ECHANGELOG_USER",
"GPG_AGENT_INFO",
"SSH_AGENT_PID", "SSH_AUTH_SOCK",
"STY", "WINDOW", "XAUTHORITY",
+ "UNIXMODE",
]
environ_whitelist = frozenset(environ_whitelist)
@@ -138,6 +143,10 @@ environ_filter += [
# misc variables inherited from the calling environment
environ_filter += [
"INFOPATH", "MANPATH", "USER",
+ "HOST", "GROUP", "LOGNAME", "MAIL", "REMOTEHOST",
+ "SECURITYSESSIONID",
+ "TERMINFO", "TERM_PROGRAM", "TERM_PROGRAM_VERSION",
+ "VENDOR", "__CF_USER_TEXT_ENCODING",
]
# variables that break bash
diff --git a/lib/portage/package/ebuild/config.py b/lib/portage/package/ebuild/config.py
index 47c180c12..c76474354 100644
--- a/lib/portage/package/ebuild/config.py
+++ b/lib/portage/package/ebuild/config.py
@@ -45,7 +45,7 @@ from portage.exception import InvalidDependString, IsADirectory, \
PortageException
from portage.localization import _
from portage.output import colorize
-from portage.process import fakeroot_capable, sandbox_capable
+from portage.process import fakeroot_capable, sandbox_capable, macossandbox_capable
from portage.repository.config import load_repository_config
from portage.util import ensure_dirs, getconfig, grabdict, \
grabdict_package, grabfile, grabfile_package, LazyItemsDict, \
@@ -898,38 +898,44 @@ class config(object):
"PORTAGE_INST_UID": "0",
}
+ # PREFIX LOCAL: inventing UID/GID based on a path is a very
+ # bad idea, it breaks almost everything since group ids
+ # don't have to match, when a user has many
+ # This in particularly breaks the configure-set portage
+ # group and user (in portage/data.py)
eroot_or_parent = first_existing(eroot)
- unprivileged = False
- try:
- eroot_st = os.stat(eroot_or_parent)
- except OSError:
- pass
- else:
-
- if portage.data._unprivileged_mode(
- eroot_or_parent, eroot_st):
- unprivileged = True
-
- default_inst_ids["PORTAGE_INST_GID"] = str(eroot_st.st_gid)
- default_inst_ids["PORTAGE_INST_UID"] = str(eroot_st.st_uid)
-
- if "PORTAGE_USERNAME" not in self:
- try:
- pwd_struct = pwd.getpwuid(eroot_st.st_uid)
- except KeyError:
- pass
- else:
- self["PORTAGE_USERNAME"] = pwd_struct.pw_name
- self.backup_changes("PORTAGE_USERNAME")
-
- if "PORTAGE_GRPNAME" not in self:
- try:
- grp_struct = grp.getgrgid(eroot_st.st_gid)
- except KeyError:
- pass
- else:
- self["PORTAGE_GRPNAME"] = grp_struct.gr_name
- self.backup_changes("PORTAGE_GRPNAME")
+ unprivileged = True
+# try:
+# eroot_st = os.stat(eroot_or_parent)
+# except OSError:
+# pass
+# else:
+#
+# if portage.data._unprivileged_mode(
+# eroot_or_parent, eroot_st):
+# unprivileged = True
+#
+# default_inst_ids["PORTAGE_INST_GID"] = str(eroot_st.st_gid)
+# default_inst_ids["PORTAGE_INST_UID"] = str(eroot_st.st_uid)
+#
+# if "PORTAGE_USERNAME" not in self:
+# try:
+# pwd_struct = pwd.getpwuid(eroot_st.st_uid)
+# except KeyError:
+# pass
+# else:
+# self["PORTAGE_USERNAME"] = pwd_struct.pw_name
+# self.backup_changes("PORTAGE_USERNAME")
+#
+# if "PORTAGE_GRPNAME" not in self:
+# try:
+# grp_struct = grp.getgrgid(eroot_st.st_gid)
+# except KeyError:
+# pass
+# else:
+# self["PORTAGE_GRPNAME"] = grp_struct.gr_name
+# self.backup_changes("PORTAGE_GRPNAME")
+ # END PREFIX LOCAL
for var, default_val in default_inst_ids.items():
try:
@@ -1187,7 +1193,7 @@ class config(object):
writemsg("!!! /etc/portage/profile/virtuals. Please move it to\n")
writemsg("!!! this new location.\n\n")
- if not sandbox_capable and \
+ if not sandbox_capable and not macossandbox_capable and \
("sandbox" in self.features or "usersandbox" in self.features):
if self.profile_path is not None and \
os.path.realpath(self.profile_path) == \
diff --git a/lib/portage/package/ebuild/doebuild.py b/lib/portage/package/ebuild/doebuild.py
index 2bff94cb1..7d685dbe4 100644
--- a/lib/portage/package/ebuild/doebuild.py
+++ b/lib/portage/package/ebuild/doebuild.py
@@ -24,6 +24,7 @@ from textwrap import wrap
import time
import warnings
import zlib
+import platform
import portage
portage.proxy.lazyimport.lazyimport(globals(),
@@ -51,7 +52,7 @@ from portage import bsd_chflags, \
unmerge, _encodings, _os_merge, \
_shell_quote, _unicode_decode, _unicode_encode
from portage.const import EBUILD_SH_ENV_FILE, EBUILD_SH_ENV_DIR, \
- EBUILD_SH_BINARY, INVALID_ENV_FILE, MISC_SH_BINARY, PORTAGE_PYM_PACKAGES
+ EBUILD_SH_BINARY, INVALID_ENV_FILE, MISC_SH_BINARY, PORTAGE_PYM_PACKAGES, EPREFIX, MACOSSANDBOX_PROFILE
from portage.data import portage_gid, portage_uid, secpass, \
uid, userpriv_groups
from portage.dbapi.porttree import _parse_uri_map
@@ -255,6 +256,12 @@ def _doebuild_path(settings, eapi=None):
path.append(x_abs)
path.extend(rootpath)
+
+ # PREFIX LOCAL: append EXTRA_PATH from make.globals
+ extrapath = [x for x in settings.get("EXTRA_PATH", "").split(":") if x]
+ path.extend(extrapath)
+ # END PREFIX LOCAL
+
settings["PATH"] = ":".join(path)
def doebuild_environment(myebuild, mydo, myroot=None, settings=None,
@@ -1369,7 +1376,8 @@ def _spawn_actionmap(settings):
"userpriv" not in restrict and \
"nouserpriv" not in restrict)
- if not portage.process.sandbox_capable:
+ if not (portage.process.sandbox_capable or \
+ portage.process.macossandbox_capable):
nosandbox = True
sesandbox = settings.selinux_enabled() and \
@@ -1613,6 +1621,10 @@ def spawn(mystring, mysettings, debug=False, free=False, droppriv=False,
user = "root"
elif portage_build_uid == portage_uid:
user = portage.data._portage_username
+ # PREFIX LOCAL: accept numeric uid
+ else:
+ user = portage_uid
+ # END PREFIX LOCAL
if user is not None:
mysettings["PORTAGE_BUILD_USER"] = user
@@ -1625,6 +1637,10 @@ def spawn(mystring, mysettings, debug=False, free=False, droppriv=False,
group = "root"
elif portage_build_gid == portage_gid:
group = portage.data._portage_grpname
+ # PREFIX LOCAL: accept numeric gid
+ else:
+ group = portage_gid
+ # END PREFIX LOCAL
if group is not None:
mysettings["PORTAGE_BUILD_GROUP"] = group
@@ -1633,7 +1649,8 @@ def spawn(mystring, mysettings, debug=False, free=False, droppriv=False,
(not droppriv and "sandbox" not in features and \
"usersandbox" not in features and not fakeroot))
- if not free and not (fakeroot or portage.process.sandbox_capable):
+ if not free and not (fakeroot or portage.process.sandbox_capable or \
+ portage.process.macossandbox_capable):
free = True
if mysettings.mycpv is not None:
@@ -1649,6 +1666,77 @@ def spawn(mystring, mysettings, debug=False, free=False, droppriv=False,
keywords["opt_name"] += " fakeroot"
keywords["fakeroot_state"] = os.path.join(mysettings["T"], "fakeroot.state")
spawn_func = portage.process.spawn_fakeroot
+ elif "sandbox" in features and platform.system() == 'Darwin':
+ keywords["opt_name"] += " macossandbox"
+ sbprofile = MACOSSANDBOX_PROFILE
+
+ # determine variable names from profile: split
+ # "text@@VARNAME@@moretext@@OTHERVAR@@restoftext" into
+ # ("text", # "VARNAME", "moretext", "OTHERVAR", "restoftext")
+ # and extract variable named by reading every second item.
+ variables = []
+ for line in sbprofile.split("\n"):
+ variables.extend(line.split("@@")[1:-1:2])
+
+ for var in variables:
+ paths = ""
+ if var in mysettings:
+ paths = mysettings[var]
+ else:
+ writemsg("Warning: sandbox profile references variable %s "
+ "which is not set.\nThe rule using it will have no "
+ "effect, which is most likely not the intended "
+ "result.\nPlease check make.conf/make.globals.\n" %
+ var)
+
+ # not set or empty value
+ if not paths:
+ sbprofile = sbprofile.replace("@@%s@@" % var, "")
+ continue
+
+ rules_literal = ""
+ rules_regex = ""
+
+ # FIXME: Allow for quoting inside the variable
+ # to allow paths with spaces in them?
+ for path in paths.split(" "):
+ # do a second round of token
+ # replacements to be able to reference
+ # settings like EPREFIX or
+ # PORTAGE_BUILDDIR.
+ for token in path.split("@@")[1:-1:2]:
+ if token not in mysettings:
+ continue
+
+ path = path.replace("@@%s@@" % token, mysettings[token])
+
+ if "@@" in path:
+ # unreplaced tokens left -
+ # silently ignore path - needed
+ # for PORTAGE_ACTUAL_DISTDIR
+ # which isn't always set
+ pass
+ elif path[-1] == os.sep:
+ # path ends in slash - make it a
+ # regex and allow access
+ # recursively.
+ path = path.replace(r'+', r'\+')
+ path = path.replace(r'*', r'\*')
+ path = path.replace(r'[', r'\[')
+ path = path.replace(r']', r'\]')
+ rules_regex += " #\"^%s\"\n" % path
+ else:
+ rules_literal += " #\"%s\"\n" % path
+
+ rules = ""
+ if rules_literal:
+ rules += " (literal\n" + rules_literal + " )\n"
+ if rules_regex:
+ rules += " (regex\n" + rules_regex + " )\n"
+ sbprofile = sbprofile.replace("@@%s@@" % var, rules)
+
+ keywords["profile"] = sbprofile
+ spawn_func = portage.process.spawn_macossandbox
else:
keywords["opt_name"] += " sandbox"
spawn_func = portage.process.spawn_sandbox
@@ -1751,6 +1839,7 @@ _post_phase_cmds = {
(
{},
[
+ "preinst_aix",
"preinst_sfperms",
"preinst_suid_scan",
"preinst_qa_check",
@@ -1758,6 +1847,7 @@ _post_phase_cmds = {
),
),
"postinst" : [
+ "postinst_aix",
"postinst_qa_check"],
}
diff --git a/lib/portage/package/ebuild/fetch.py b/lib/portage/package/ebuild/fetch.py
index 9682fea89..11b13fe56 100644
--- a/lib/portage/package/ebuild/fetch.py
+++ b/lib/portage/package/ebuild/fetch.py
@@ -51,6 +51,7 @@ from portage.checksum import (get_valid_checksum_keys, perform_md5, verify_all,
checksum_str)
from portage.const import BASH_BINARY, CUSTOM_MIRRORS_FILE, \
GLOBAL_CONFIG_PATH
+from portage.const import rootgid
from portage.data import portage_gid, portage_uid, userpriv_groups
from portage.exception import FileNotFound, OperationNotPermitted, \
PortageException, TryAgain
@@ -209,7 +210,7 @@ def _ensure_distdir(settings, distdir):
# to have root's gid. Therefore, use root's gid instead of
# portage's gid to avoid spurrious permissions adjustments
# when inside fakeroot.
- dir_gid = 0
+ dir_gid = rootgid
userfetch = portage.data.secpass >= 2 and "userfetch" in settings.features
userpriv = portage.data.secpass >= 2 and "userpriv" in settings.features
diff --git a/lib/portage/process.py b/lib/portage/process.py
index ceb454030..3e5d2e4ef 100644
--- a/lib/portage/process.py
+++ b/lib/portage/process.py
@@ -23,7 +23,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
'portage.util:dump_traceback,writemsg',
)
-from portage.const import BASH_BINARY, SANDBOX_BINARY, FAKEROOT_BINARY
+from portage.const import BASH_BINARY, SANDBOX_BINARY, MACOSSANDBOX_BINARY, FAKEROOT_BINARY
from portage.exception import CommandNotFound
from portage.util._ctypes import find_library, LoadLibrary, ctypes
@@ -99,6 +99,8 @@ sandbox_capable = (os.path.isfile(SANDBOX_BINARY) and
fakeroot_capable = (os.path.isfile(FAKEROOT_BINARY) and
os.access(FAKEROOT_BINARY, os.X_OK))
+macossandbox_capable = (os.path.isfile(MACOSSANDBOX_BINARY) and
+ os.access(MACOSSANDBOX_BINARY, os.X_OK))
def sanitize_fds():
"""
@@ -172,6 +174,19 @@ def spawn_fakeroot(mycommand, fakeroot_state=None, opt_name=None, **keywords):
args.append(mycommand)
return spawn(args, opt_name=opt_name, **keywords)
+def spawn_macossandbox(mycommand, profile=None, opt_name=None, **keywords):
+ if not macossandbox_capable:
+ return spawn_bash(mycommand, opt_name=opt_name, **keywords)
+ args=[MACOSSANDBOX_BINARY]
+ if not opt_name:
+ opt_name = os.path.basename(mycommand.split()[0])
+ args.append("-p")
+ args.append(profile)
+ 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
diff --git a/lib/portage/tests/lazyimport/test_lazy_import_portage_baseline.py b/lib/portage/tests/lazyimport/test_lazy_import_portage_baseline.py
index 080cf3f98..2bc54698a 100644
--- a/lib/portage/tests/lazyimport/test_lazy_import_portage_baseline.py
+++ b/lib/portage/tests/lazyimport/test_lazy_import_portage_baseline.py
@@ -20,6 +20,7 @@ class LazyImportPortageBaselineTestCase(TestCase):
'portage.proxy', 'portage.proxy.lazyimport',
'portage.proxy.objectproxy',
'portage._selinux',
+ 'portage.const_autotool',
])
_baseline_import_cmd = [portage._python_interpreter, '-c', '''
diff --git a/lib/portage/tests/resolver/ResolverPlayground.py b/lib/portage/tests/resolver/ResolverPlayground.py
index de80a0cc1..0751e392e 100644
--- a/lib/portage/tests/resolver/ResolverPlayground.py
+++ b/lib/portage/tests/resolver/ResolverPlayground.py
@@ -286,6 +286,7 @@ class ResolverPlayground(object):
metadata["repository"] = repo
metadata["CATEGORY"] = cat
metadata["PF"] = pf
+ metadata["EPREFIX"] = self.eprefix
repo_dir = self.pkgdir
category_dir = os.path.join(repo_dir, cat)
diff --git a/lib/portage/tests/runTests.py b/lib/portage/tests/runTests.py
index d4d1f7c76..2f9a7ad47 100755
--- a/lib/portage/tests/runTests.py
+++ b/lib/portage/tests/runTests.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python -bWd
+#!@PREFIX_PORTAGE_PYTHON@ -bWd
# runTests.py -- Portage Unit Test Functionality
# Copyright 2006-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
@@ -24,8 +24,14 @@ signal.signal(debug_signum, debug_signal)
# Pretend that the current user's uid/gid are the 'portage' uid/gid,
# so things go smoothly regardless of the current user and global
# user/group configuration.
-os.environ["PORTAGE_USERNAME"] = pwd.getpwuid(os.getuid()).pw_name
-os.environ["PORTAGE_GRPNAME"] = grp.getgrgid(os.getgid()).gr_name
+try:
+ os.environ["PORTAGE_USERNAME"] = pwd.getpwuid(os.getuid()).pw_name
+except KeyError:
+ os.environ["PORTAGE_USERNAME"] = str(os.getuid())
+try:
+ os.environ["PORTAGE_GRPNAME"] = grp.getgrgid(os.getgid()).gr_name
+except KeyError:
+ os.environ["PORTAGE_GRPNAME"] = str(os.getgid())
# Insert our parent dir so we can do shiny import "tests"
# This line courtesy of Marienz and Pkgcore ;)
diff --git a/lib/portage/util/__init__.py b/lib/portage/util/__init__.py
index 154431a53..6bff97fb7 100644
--- a/lib/portage/util/__init__.py
+++ b/lib/portage/util/__init__.py
@@ -48,6 +48,7 @@ from portage.exception import InvalidAtom, PortageException, FileNotFound, \
from portage.localization import _
from portage.proxy.objectproxy import ObjectProxy
from portage.cache.mappings import UserDict
+from portage.const import EPREFIX
if sys.hexversion >= 0x3000000:
_unicode = str
@@ -1837,10 +1838,22 @@ def getlibpaths(root, env=None):
""" Return a list of paths that are used for library lookups """
if env is None:
env = os.environ
+
+ # PREFIX HACK: LD_LIBRARY_PATH isn't portable, and considered
+ # harmfull, so better not use it. We don't need any host OS lib
+ # paths either, so do Prefix case.
+ if EPREFIX != '':
+ rval = []
+ rval.append(EPREFIX + "/usr/lib")
+ rval.append(EPREFIX + "/lib")
+ # we don't know the CHOST here, so it's a bit hard to guess
+ # where GCC's and ld's libs are. Though, GCC's libs should be
+ # in lib and usr/lib, binutils' libs rarely used
+ else:
# the following is based on the information from ld.so(8)
- rval = env.get("LD_LIBRARY_PATH", "").split(":")
- rval.extend(read_ld_so_conf(os.path.join(root, "etc", "ld.so.conf")))
- rval.append("/usr/lib")
- rval.append("/lib")
+ rval = env.get("LD_LIBRARY_PATH", "").split(":")
+ rval.extend(read_ld_so_conf(os.path.join(root, "etc", "ld.so.conf")))
+ rval.append("/usr/lib")
+ rval.append("/lib")
return [normalize_path(x) for x in rval if x]
diff --git a/lib/portage/util/_dyn_libs/LinkageMapMachO.py b/lib/portage/util/_dyn_libs/LinkageMapMachO.py
new file mode 100644
index 000000000..e74f0c5ba
--- /dev/null
+++ b/lib/portage/util/_dyn_libs/LinkageMapMachO.py
@@ -0,0 +1,773 @@
+# Copyright 1998-2019 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+import errno
+import logging
+import subprocess
+
+import portage
+from portage import _encodings
+from portage import _os_merge
+from portage import _unicode_decode
+from portage import _unicode_encode
+from portage.cache.mappings import slot_dict_class
+from portage.exception import CommandNotFound
+from portage.localization import _
+from portage.util import getlibpaths
+from portage.util import grabfile
+from portage.util import normalize_path
+from portage.util import writemsg_level
+from portage.const import EPREFIX
+
+class LinkageMapMachO(object):
+
+ """Models dynamic linker dependencies."""
+
+ _needed_aux_key = "NEEDED.MACHO.3"
+ _installname_map_class = slot_dict_class(
+ ("consumers", "providers"), prefix="")
+
+ class _obj_properties_class(object):
+
+ __slots__ = ("arch", "needed", "install_name", "alt_paths",
+ "owner",)
+
+ def __init__(self, arch, needed, install_name, alt_paths, owner):
+ self.arch = arch
+ self.needed = needed
+ self.install_name = install_name
+ self.alt_paths = alt_paths
+ self.owner = owner
+
+ def __init__(self, vardbapi):
+ self._dbapi = vardbapi
+ self._root = self._dbapi.settings['ROOT']
+ self._libs = {}
+ self._obj_properties = {}
+ self._obj_key_cache = {}
+ self._path_key_cache = {}
+
+ def _clear_cache(self):
+ self._libs.clear()
+ self._obj_properties.clear()
+ self._obj_key_cache.clear()
+ self._path_key_cache.clear()
+
+ def _path_key(self, path):
+ key = self._path_key_cache.get(path)
+ if key is None:
+ key = self._ObjectKey(path, self._root)
+ self._path_key_cache[path] = key
+ return key
+
+ def _obj_key(self, path):
+ key = self._obj_key_cache.get(path)
+ if key is None:
+ key = self._ObjectKey(path, self._root)
+ self._obj_key_cache[path] = key
+ return key
+
+ class _ObjectKey(object):
+
+ """Helper class used as _obj_properties keys for objects."""
+
+ __slots__ = ("_key",)
+
+ def __init__(self, obj, root):
+ """
+ This takes a path to an object.
+
+ @param object: path to a file
+ @type object: string (example: '/usr/bin/bar')
+
+ """
+ self._key = self._generate_object_key(obj, root)
+
+ def __hash__(self):
+ return hash(self._key)
+
+ def __eq__(self, other):
+ return self._key == other._key
+
+ def _generate_object_key(self, obj, root):
+ """
+ Generate object key for a given object.
+
+ @param object: path to a file
+ @type object: string (example: '/usr/bin/bar')
+ @rtype: 2-tuple of types (long, int) if object exists. string if
+ object does not exist.
+ @return:
+ 1. 2-tuple of object's inode and device from a stat call, if object
+ exists.
+ 2. realpath of object if object does not exist.
+
+ """
+
+ os = _os_merge
+
+ try:
+ _unicode_encode(obj,
+ encoding=_encodings['merge'], errors='strict')
+ except UnicodeEncodeError:
+ # The package appears to have been merged with a
+ # different value of sys.getfilesystemencoding(),
+ # so fall back to utf_8 if appropriate.
+ try:
+ _unicode_encode(obj,
+ encoding=_encodings['fs'], errors='strict')
+ except UnicodeEncodeError:
+ pass
+ else:
+ os = portage.os
+
+ abs_path = os.path.join(root, obj.lstrip(os.sep))
+ try:
+ object_stat = os.stat(abs_path)
+ except OSError:
+ # Use the realpath as the key if the file does not exists on the
+ # filesystem.
+ return os.path.realpath(abs_path)
+ # Return a tuple of the device and inode.
+ return (object_stat.st_dev, object_stat.st_ino)
+
+ def file_exists(self):
+ """
+ Determine if the file for this key exists on the filesystem.
+
+ @rtype: Boolean
+ @return:
+ 1. True if the file exists.
+ 2. False if the file does not exist or is a broken symlink.
+
+ """
+ return isinstance(self._key, tuple)
+
+ class _LibGraphNode(_ObjectKey):
+ __slots__ = ("alt_paths",)
+
+ def __init__(self, key):
+ """
+ Create a _LibGraphNode from an existing _ObjectKey.
+ This re-uses the _key attribute in order to avoid repeating
+ any previous stat calls, which helps to avoid potential race
+ conditions due to inconsistent stat results when the
+ file system is being modified concurrently.
+ """
+ self._key = key._key
+ self.alt_paths = set()
+
+ def __str__(self):
+ return str(sorted(self.alt_paths))
+
+ def rebuild(self, exclude_pkgs=None, include_file=None,
+ preserve_paths=None):
+ """
+ Raises CommandNotFound if there are preserved libs
+ and the scanmacho binary is not available.
+
+ @param exclude_pkgs: A set of packages that should be excluded from
+ the LinkageMap, since they are being unmerged and their NEEDED
+ entries are therefore irrelevant and would only serve to corrupt
+ the LinkageMap.
+ @type exclude_pkgs: set
+ @param include_file: The path of a file containing NEEDED entries for
+ a package which does not exist in the vardbapi yet because it is
+ currently being merged.
+ @type include_file: String
+ @param preserve_paths: Libraries preserved by a package instance that
+ is currently being merged. They need to be explicitly passed to the
+ LinkageMap, since they are not registered in the
+ PreservedLibsRegistry yet.
+ @type preserve_paths: set
+ """
+
+ os = _os_merge
+ root = self._root
+ root_len = len(root) - 1
+ self._clear_cache()
+ libs = self._libs
+ obj_properties = self._obj_properties
+
+ lines = []
+
+ # Data from include_file is processed first so that it
+ # overrides any data from previously installed files.
+ if include_file is not None:
+ for line in grabfile(include_file):
+ lines.append((None, include_file, line))
+
+ aux_keys = [self._needed_aux_key]
+ can_lock = os.access(os.path.dirname(self._dbapi._dbroot), os.W_OK)
+ if can_lock:
+ self._dbapi.lock()
+ try:
+ for cpv in self._dbapi.cpv_all():
+ if exclude_pkgs is not None and cpv in exclude_pkgs:
+ continue
+ needed_file = self._dbapi.getpath(cpv,
+ filename=self._needed_aux_key)
+ for line in self._dbapi.aux_get(cpv, aux_keys)[0].splitlines():
+ lines.append((cpv, needed_file, line))
+ finally:
+ if can_lock:
+ self._dbapi.unlock()
+
+ # have to call scanmacho for preserved libs here as they aren't
+ # registered in NEEDED.MACHO.3 files
+ plibs = {}
+ if preserve_paths is not None:
+ plibs.update((x, None) for x in preserve_paths)
+ if self._dbapi._plib_registry and \
+ self._dbapi._plib_registry.hasEntries():
+ for cpv, items in \
+ self._dbapi._plib_registry.getPreservedLibs().items():
+ if exclude_pkgs is not None and cpv in exclude_pkgs:
+ # These preserved libs will either be unmerged,
+ # rendering them irrelevant, or they will be
+ # preserved in the replacement package and are
+ # already represented via the preserve_paths
+ # parameter.
+ continue
+ plibs.update((x, cpv) for x in items)
+ if plibs:
+ args = [os.path.join(EPREFIX or "/", "usr/bin/scanmacho"), "-qF", "%a;%F;%S;%n"]
+ args.extend(os.path.join(root, x.lstrip("." + os.sep)) \
+ for x in plibs)
+ try:
+ proc = subprocess.Popen(args, stdout=subprocess.PIPE)
+ except EnvironmentError as e:
+ if e.errno != errno.ENOENT:
+ raise
+ raise CommandNotFound(args[0])
+ else:
+ for l in proc.stdout:
+ try:
+ l = _unicode_decode(l,
+ encoding=_encodings['content'], errors='strict')
+ except UnicodeDecodeError:
+ l = _unicode_decode(l,
+ encoding=_encodings['content'], errors='replace')
+ writemsg_level(_("\nError decoding characters " \
+ "returned from scanmacho: %s\n\n") % (l,),
+ level=logging.ERROR, noiselevel=-1)
+ l = l.rstrip("\n")
+ if not l:
+ continue
+ fields = l.split(";")
+ if len(fields) < 4:
+ writemsg_level("\nWrong number of fields " + \
+ "returned from scanmacho: %s\n\n" % (l,),
+ level=logging.ERROR, noiselevel=-1)
+ continue
+ fields[1] = fields[1][root_len:]
+ owner = plibs.pop(fields[1], None)
+ lines.append((owner, "scanmacho", ";".join(fields)))
+ proc.wait()
+ proc.stdout.close()
+
+ if plibs:
+ # Preserved libraries that did not appear in the scanmacho output.
+ # This is known to happen with statically linked libraries.
+ # Generate dummy lines for these, so we can assume that every
+ # preserved library has an entry in self._obj_properties. This
+ # is important in order to prevent findConsumers from raising
+ # an unwanted KeyError.
+ for x, cpv in plibs.items():
+ lines.append((cpv, "plibs", ";".join(['', x, '', '', ''])))
+
+ # Share identical frozenset instances when available,
+ # in order to conserve memory.
+ frozensets = {}
+
+ for owner, location, l in lines:
+ l = l.rstrip("\n")
+ if not l:
+ continue
+ fields = l.split(";")
+ if len(fields) < 4:
+ writemsg_level(_("\nWrong number of fields " \
+ "in %s: %s\n\n") % (location, l),
+ level=logging.ERROR, noiselevel=-1)
+ continue
+ arch = fields[0]
+ obj = fields[1]
+ install_name = os.path.normpath(fields[2])
+ needed = frozenset(x for x in fields[3].split(",") if x)
+ needed = frozensets.setdefault(needed, needed)
+
+ obj_key = self._obj_key(obj)
+ indexed = True
+ myprops = obj_properties.get(obj_key)
+ if myprops is None:
+ indexed = False
+ myprops = self._obj_properties_class(
+ arch, needed, install_name, [], owner)
+ obj_properties[obj_key] = myprops
+ # All object paths are added into the obj_properties tuple.
+ myprops.alt_paths.append(obj)
+
+ # Don't index the same file more that once since only one
+ # set of data can be correct and therefore mixing data
+ # may corrupt the index (include_file overrides previously
+ # installed).
+ if indexed:
+ continue
+
+ arch_map = libs.get(arch)
+ if arch_map is None:
+ arch_map = {}
+ libs[arch] = arch_map
+ if install_name:
+ installname_map = arch_map.get(install_name)
+ if installname_map is None:
+ installname_map = self._installname_map_class(
+ providers=[], consumers=[])
+ arch_map[install_name] = installname_map
+ installname_map.providers.append(obj_key)
+ for needed_installname in needed:
+ installname_map = arch_map.get(needed_installname)
+ if installname_map is None:
+ installname_map = self._installname_map_class(
+ providers=[], consumers=[])
+ arch_map[needed_installname] = installname_map
+ installname_map.consumers.append(obj_key)
+
+ for arch, install_names in libs.items():
+ for install_name_node in install_names.values():
+ install_name_node.providers = tuple(set(install_name_node.providers))
+ install_name_node.consumers = tuple(set(install_name_node.consumers))
+
+ def listBrokenBinaries(self, debug=False):
+ """
+ Find binaries and their needed install_names, which have no providers.
+
+ @param debug: Boolean to enable debug output
+ @type debug: Boolean
+ @rtype: dict (example: {'/usr/bin/foo': set(['/usr/lib/libbar.dylib'])})
+ @return: The return value is an object -> set-of-install_names mapping, where
+ object is a broken binary and the set consists of install_names needed by
+ object that have no corresponding libraries to fulfill the dependency.
+
+ """
+
+ os = _os_merge
+
+ class _LibraryCache(object):
+
+ """
+ Caches properties associated with paths.
+
+ The purpose of this class is to prevent multiple instances of
+ _ObjectKey for the same paths.
+
+ """
+
+ def __init__(cache_self):
+ cache_self.cache = {}
+
+ def get(cache_self, obj):
+ """
+ Caches and returns properties associated with an object.
+
+ @param obj: absolute path (can be symlink)
+ @type obj: string (example: '/usr/lib/libfoo.dylib')
+ @rtype: 4-tuple with types
+ (string or None, string or None, 2-tuple, Boolean)
+ @return: 4-tuple with the following components:
+ 1. arch as a string or None if it does not exist,
+ 2. soname as a string or None if it does not exist,
+ 3. obj_key as 2-tuple,
+ 4. Boolean representing whether the object exists.
+ (example: ('libfoo.1.dylib', (123L, 456L), True))
+
+ """
+ if obj in cache_self.cache:
+ return cache_self.cache[obj]
+ else:
+ obj_key = self._obj_key(obj)
+ # Check that the library exists on the filesystem.
+ if obj_key.file_exists():
+ # Get the install_name from LinkageMapMachO._obj_properties if
+ # it exists. Otherwise, None.
+ obj_props = self._obj_properties.get(obj_key)
+ if obj_props is None:
+ arch = None
+ install_name = None
+ else:
+ arch = obj_props.arch
+ install_name = obj_props.install_name
+ return cache_self.cache.setdefault(obj, \
+ (arch, install_name, obj_key, True))
+ else:
+ return cache_self.cache.setdefault(obj, \
+ (None, None, obj_key, False))
+
+ rValue = {}
+ cache = _LibraryCache()
+ providers = self.listProviders()
+
+ # Iterate over all obj_keys and their providers.
+ for obj_key, install_names in providers.items():
+ obj_props = self._obj_properties[obj_key]
+ arch = obj_props.arch
+ objs = obj_props.alt_paths
+ # Iterate over each needed install_name and the set of
+ # library paths that fulfill the install_name to determine
+ # if the dependency is broken.
+ for install_name, libraries in install_names.items():
+ # validLibraries is used to store libraries, which
+ # satisfy install_name, so if no valid libraries are
+ # found, the install_name is not satisfied for obj_key.
+ # If unsatisfied, objects associated with obj_key must
+ # be emerged.
+ validLibrary = set() # for compat with LinkageMap
+ cachedArch, cachedInstallname, cachedKey, cachedExists = \
+ cache.get(install_name)
+ # Check that the this library provides the needed soname. Doing
+ # this, however, will cause consumers of libraries missing
+ # sonames to be unnecessarily emerged. (eg libmix.so)
+ if cachedInstallname == install_name and cachedArch == arch:
+ validLibrary.add(cachedKey)
+ if debug and cachedKey not in \
+ set(map(self._obj_key_cache.get, libraries)):
+ # XXX This is most often due to soname symlinks not in
+ # a library's directory. We could catalog symlinks in
+ # LinkageMap to avoid checking for this edge case here.
+ print(_("Found provider outside of findProviders:"), \
+ install_name, "->", cachedRealpath)
+ if debug and cachedArch == arch and \
+ cachedKey in self._obj_properties:
+ print(_("Broken symlink or missing/bad install_name:"), \
+ install_name, '->', cachedRealpath, \
+ "with install_name", cachedInstallname, "but expecting", install_name)
+ # This conditional checks if there are no libraries to
+ # satisfy the install_name (empty set).
+ if not validLibrary:
+ for obj in objs:
+ rValue.setdefault(obj, set()).add(install_name)
+ # If no valid libraries have been found by this
+ # point, then the install_name does not exist in the
+ # filesystem, but if there are libraries (from the
+ # providers mapping), it is likely that soname
+ # symlinks or the actual libraries are missing or
+ # broken. Thus those libraries are added to rValue
+ # in order to emerge corrupt library packages.
+ for lib in libraries:
+ rValue.setdefault(lib, set()).add(install_name)
+ if debug:
+ if not os.path.isfile(lib):
+ writemsg_level(_("Missing library:") + " %s\n" % (lib,),
+ level=logging.DEBUG,
+ noiselevel=-1)
+ else:
+ writemsg_level(_("Possibly missing symlink:") + \
+ "%s\n" % (os.path.join(os.path.dirname(lib), soname)),
+ level=logging.DEBUG,
+ noiselevel=-1)
+ return rValue
+
+ def listProviders(self):
+ """
+ Find the providers for all object keys in LinkageMap.
+
+ @rtype: dict (example:
+ {(123L, 456L): {'libbar.dylib': set(['/lib/libbar.1.5.dylib'])}})
+ @return: The return value is an object -> providers mapping, where
+ providers is a mapping of install_name -> set-of-library-paths returned
+ from the findProviders method.
+
+ """
+ rValue = {}
+ if not self._libs:
+ self.rebuild()
+ # Iterate over all object keys within LinkageMap.
+ for obj_key in self._obj_properties:
+ rValue.setdefault(obj_key, self.findProviders(obj_key))
+ return rValue
+
+ def isMasterLink(self, obj):
+ """
+ Determine whether an object is a "master" symlink, which means
+ that its basename is the same as the beginning part of the
+ install_name and it lacks the install_name's version component.
+
+ Examples:
+
+ install_name | master symlink name
+ -----------------------------------------------
+ libarchive.2.8.4.dylib | libarchive.dylib
+ (typically the install_name is libarchive.2.dylib)
+
+ @param obj: absolute path to an object
+ @type obj: string (example: '/usr/bin/foo')
+ @rtype: Boolean
+ @return:
+ 1. True if obj is a master link
+ 2. False if obj is not a master link
+
+ """
+ os = _os_merge
+ obj_key = self._obj_key(obj)
+ if obj_key not in self._obj_properties:
+ raise KeyError("%s (%s) not in object list" % (obj_key, obj))
+ basename = os.path.basename(obj)
+ install_name = self._obj_properties[obj_key].install_name
+ return (len(basename) < len(os.path.basename(install_name)) and \
+ basename.endswith(".dylib") and \
+ os.path.basename(install_name).startswith(basename[:-6]))
+
+ def listLibraryObjects(self):
+ """
+ Return a list of library objects.
+
+ Known limitation: library objects lacking an soname are not included.
+
+ @rtype: list of strings
+ @return: list of paths to all providers
+
+ """
+ rValue = []
+ if not self._libs:
+ self.rebuild()
+ for arch_map in self._libs.values():
+ for soname_map in arch_map.values():
+ for obj_key in soname_map.providers:
+ rValue.extend(self._obj_properties[obj_key].alt_paths)
+ return rValue
+
+ def getOwners(self, obj):
+ """
+ Return the package(s) associated with an object. Raises KeyError
+ if the object is unknown. Returns an empty tuple if the owner(s)
+ are unknown.
+
+ NOTE: For preserved libraries, the owner(s) may have been
+ previously uninstalled, but these uninstalled owners can be
+ returned by this method since they are registered in the
+ PreservedLibsRegistry.
+
+ @param obj: absolute path to an object
+ @type obj: string (example: '/usr/bin/bar')
+ @rtype: tuple
+ @return: a tuple of cpv
+ """
+ if not self._libs:
+ self.rebuild()
+ if isinstance(obj, self._ObjectKey):
+ obj_key = obj
+ else:
+ obj_key = self._obj_key_cache.get(obj)
+ if obj_key is None:
+ raise KeyError("%s not in object list" % obj)
+ obj_props = self._obj_properties.get(obj_key)
+ if obj_props is None:
+ raise KeyError("%s not in object list" % obj_key)
+ if obj_props.owner is None:
+ return ()
+ return (obj_props.owner,)
+
+ def getSoname(self, obj):
+ """
+ Return the install_name associated with an object. To match
+ soname behaviour, the leading path is stripped.
+
+ @param obj: absolute path to an object
+ @type obj: string (example: '/usr/bin/bar')
+ @rtype: string
+ @return: install_name basename as a string
+
+ """
+ os = _os_merge
+ if not self._libs:
+ self.rebuild()
+ if isinstance(obj, self._ObjectKey):
+ obj_key = obj
+ if obj_key not in self._obj_properties:
+ raise KeyError("%s not in object list" % obj_key)
+ return os.path.basename(self._obj_properties[obj_key].install_name)
+ if obj not in self._obj_key_cache:
+ raise KeyError("%s not in object list" % obj)
+ return os.path.basename(
+ self._obj_properties[self._obj_key_cache[obj]].install_name)
+
+ def findProviders(self, obj):
+ """
+ Find providers for an object or object key.
+
+ This method may be called with a key from _obj_properties.
+
+ In some cases, not all valid libraries are returned. This may occur when
+ an soname symlink referencing a library is in an object's runpath while
+ the actual library is not. We should consider cataloging symlinks within
+ LinkageMap as this would avoid those cases and would be a better model of
+ library dependencies (since the dynamic linker actually searches for
+ files named with the soname in the runpaths).
+
+ @param obj: absolute path to an object or a key from _obj_properties
+ @type obj: string (example: '/usr/bin/bar') or _ObjectKey
+ @rtype: dict (example: {'libbar.dylib': set(['/lib/libbar.1.5.dylib'])})
+ @return: The return value is a install_name -> set-of-library-paths, where
+ set-of-library-paths satisfy install_name.
+
+ """
+
+ os = _os_merge
+
+ rValue = {}
+
+ if not self._libs:
+ self.rebuild()
+
+ # Determine the obj_key from the arguments.
+ if isinstance(obj, self._ObjectKey):
+ obj_key = obj
+ if obj_key not in self._obj_properties:
+ raise KeyError("%s not in object list" % obj_key)
+ else:
+ obj_key = self._obj_key(obj)
+ if obj_key not in self._obj_properties:
+ raise KeyError("%s (%s) not in object list" % (obj_key, obj))
+
+ obj_props = self._obj_properties[obj_key]
+ arch = obj_props.arch
+ needed = obj_props.needed
+ install_name = obj_props.install_name
+ for install_name in needed:
+ rValue[install_name] = set()
+ if arch not in self._libs or install_name not in self._libs[arch]:
+ continue
+ # For each potential provider of the install_name, add it to
+ # rValue if it exists. (Should be one)
+ for provider_key in self._libs[arch][install_name].providers:
+ providers = self._obj_properties[provider_key].alt_paths
+ for provider in providers:
+ if os.path.exists(provider):
+ rValue[install_name].add(provider)
+ return rValue
+
+ def findConsumers(self, obj, exclude_providers=None, greedy=True):
+ """
+ Find consumers of an object or object key.
+
+ This method may be called with a key from _obj_properties. If this
+ method is going to be called with an object key, to avoid not catching
+ shadowed libraries, do not pass new _ObjectKey instances to this method.
+ Instead pass the obj as a string.
+
+ In some cases, not all consumers are returned. This may occur when
+ an soname symlink referencing a library is in an object's runpath while
+ the actual library is not. For example, this problem is noticeable for
+ binutils since it's libraries are added to the path via symlinks that
+ are gemerated in the /usr/$CHOST/lib/ directory by binutils-config.
+ Failure to recognize consumers of these symlinks makes preserve-libs
+ fail to preserve binutils libs that are needed by these unrecognized
+ consumers.
+
+ Note that library consumption via dlopen (common for kde plugins) is
+ currently undetected. However, it is possible to use the
+ corresponding libtool archive (*.la) files to detect such consumers
+ (revdep-rebuild is able to detect them).
+
+ The exclude_providers argument is useful for determining whether
+ removal of one or more packages will create unsatisfied consumers. When
+ this option is given, consumers are excluded from the results if there
+ is an alternative provider (which is not excluded) of the required
+ soname such that the consumers will remain satisfied if the files
+ owned by exclude_providers are removed.
+
+ @param obj: absolute path to an object or a key from _obj_properties
+ @type obj: string (example: '/usr/bin/bar') or _ObjectKey
+ @param exclude_providers: A collection of callables that each take a
+ single argument referring to the path of a library (example:
+ '/usr/lib/libssl.0.9.8.dylib'), and return True if the library is
+ owned by a provider which is planned for removal.
+ @type exclude_providers: collection
+ @param greedy: If True, then include consumers that are satisfied
+ by alternative providers, otherwise omit them. Default is True.
+ @type greedy: Boolean
+ @rtype: set of strings (example: set(['/bin/foo', '/usr/bin/bar']))
+ @return: The return value is a install_name -> set-of-library-paths, where
+ set-of-library-paths satisfy install_name.
+
+ """
+
+ os = _os_merge
+
+ if not self._libs:
+ self.rebuild()
+
+ # Determine the obj_key and the set of objects matching the arguments.
+ if isinstance(obj, self._ObjectKey):
+ obj_key = obj
+ if obj_key not in self._obj_properties:
+ raise KeyError("%s not in object list" % obj_key)
+ objs = self._obj_properties[obj_key].alt_paths
+ else:
+ objs = set([obj])
+ obj_key = self._obj_key(obj)
+ if obj_key not in self._obj_properties:
+ raise KeyError("%s (%s) not in object list" % (obj_key, obj))
+
+ # If there is another version of this lib with the
+ # same install_name and the install_name symlink points to that
+ # other version, this lib will be shadowed and won't
+ # have any consumers.
+ if not isinstance(obj, self._ObjectKey):
+ install_name = self._obj_properties[obj_key].install_name
+ master_link = os.path.join(self._root,
+ install_name.lstrip(os.path.sep))
+ obj_path = os.path.join(self._root, obj.lstrip(os.sep))
+ try:
+ master_st = os.stat(master_link)
+ obj_st = os.stat(obj_path)
+ except OSError:
+ pass
+ else:
+ if (obj_st.st_dev, obj_st.st_ino) != \
+ (master_st.st_dev, master_st.st_ino):
+ return set()
+
+ obj_props = self._obj_properties[obj_key]
+ arch = obj_props.arch
+ install_name = obj_props.install_name
+
+ install_name_node = None
+ arch_map = self._libs.get(arch)
+ if arch_map is not None:
+ install_name_node = arch_map.get(install_name)
+
+ satisfied_consumer_keys = set()
+ if install_name_node is not None:
+ if exclude_providers is not None and not greedy:
+ relevant_dir_keys = set()
+ for provider_key in install_name_node.providers:
+ if not greedy and provider_key == obj_key:
+ continue
+ provider_objs = self._obj_properties[provider_key].alt_paths
+ for p in provider_objs:
+ provider_excluded = False
+ if exclude_providers is not None:
+ for excluded_provider_isowner in exclude_providers:
+ if excluded_provider_isowner(p):
+ provider_excluded = True
+ break
+ if not provider_excluded:
+ # This provider is not excluded. It will
+ # satisfy a consumer of this install_name.
+ relevant_dir_keys.add(self._path_key(p))
+
+ if relevant_dir_keys:
+ for consumer_key in install_name_node.consumers:
+ satisfied_consumer_keys.add(consumer_key)
+
+ rValue = set()
+ if install_name_node is not None:
+ # For each potential consumer, add it to rValue.
+ for consumer_key in install_name_node.consumers:
+ if consumer_key in satisfied_consumer_keys:
+ continue
+ consumer_props = self._obj_properties[consumer_key]
+ consumer_objs = consumer_props.alt_paths
+ rValue.update(consumer_objs)
+ return rValue
diff --git a/lib/portage/util/_dyn_libs/LinkageMapPeCoff.py b/lib/portage/util/_dyn_libs/LinkageMapPeCoff.py
new file mode 100644
index 000000000..fd0ab6ee8
--- /dev/null
+++ b/lib/portage/util/_dyn_libs/LinkageMapPeCoff.py
@@ -0,0 +1,286 @@
+# Copyright 1998-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+import errno
+import logging
+import subprocess
+
+import portage
+from portage import _encodings
+from portage import _os_merge
+from portage import _unicode_decode
+from portage import _unicode_encode
+from portage.cache.mappings import slot_dict_class
+from portage.exception import CommandNotFound
+from portage.localization import _
+from portage.util import getlibpaths
+from portage.util import grabfile
+from portage.util import normalize_path
+from portage.util import writemsg_level
+from portage.const import EPREFIX
+from portage.util._dyn_libs.LinkageMapELF import LinkageMapELF
+
+class LinkageMapPeCoff(LinkageMapELF):
+
+ """Models dynamic linker dependencies."""
+
+ # NEEDED.PECOFF.1 has effectively the _same_ format as NEEDED.ELF.2,
+ # but we keep up the relation "scanelf" -> "NEEDED.ELF", "readpecoff" ->
+ # "NEEDED.PECOFF", "scanmacho" -> "NEEDED.MACHO", etc. others will follow.
+ _needed_aux_key = "NEEDED.PECOFF.1"
+
+ class _ObjectKey(LinkageMapELF._ObjectKey):
+
+ """Helper class used as _obj_properties keys for objects."""
+
+ def _generate_object_key(self, obj, root):
+ """
+ Generate object key for a given object. This is different from the
+ Linux implementation, since some systems (e.g. interix) don't have
+ "inodes", thus the inode field is always zero, or a random value,
+ making it inappropriate for identifying a file... :)
+
+ @param object: path to a file
+ @type object: string (example: '/usr/bin/bar')
+ @rtype: 2-tuple of types (bool, string)
+ @return:
+ 2-tuple of boolean indicating existance, and absolut path
+ """
+
+ os = _os_merge
+
+ try:
+ _unicode_encode(obj,
+ encoding=_encodings['merge'], errors='strict')
+ except UnicodeEncodeError:
+ # The package appears to have been merged with a
+ # different value of sys.getfilesystemencoding(),
+ # so fall back to utf_8 if appropriate.
+ try:
+ _unicode_encode(obj,
+ encoding=_encodings['fs'], errors='strict')
+ except UnicodeEncodeError:
+ pass
+ else:
+ os = portage.os
+
+ abs_path = os.path.join(root, obj.lstrip(os.sep))
+ try:
+ object_stat = os.stat(abs_path)
+ except OSError:
+ return (False, os.path.realpath(abs_path))
+ # On Interix, the inode field may always be zero, since the
+ # filesystem (NTFS) has no inodes ...
+ return (True, os.path.realpath(abs_path))
+
+ def file_exists(self):
+ """
+ Determine if the file for this key exists on the filesystem.
+
+ @rtype: Boolean
+ @return:
+ 1. True if the file exists.
+ 2. False if the file does not exist or is a broken symlink.
+
+ """
+ return self._key[0]
+
+ class _LibGraphNode(_ObjectKey):
+ __slots__ = ("alt_paths",)
+
+ def __init__(self, key):
+ """
+ Create a _LibGraphNode from an existing _ObjectKey.
+ This re-uses the _key attribute in order to avoid repeating
+ any previous stat calls, which helps to avoid potential race
+ conditions due to inconsistent stat results when the
+ file system is being modified concurrently.
+ """
+ self._key = key._key
+ self.alt_paths = set()
+
+ def __str__(self):
+ return str(sorted(self.alt_paths))
+
+ def rebuild(self, exclude_pkgs=None, include_file=None,
+ preserve_paths=None):
+ """
+ Raises CommandNotFound if there are preserved libs
+ and the readpecoff binary is not available.
+
+ @param exclude_pkgs: A set of packages that should be excluded from
+ the LinkageMap, since they are being unmerged and their NEEDED
+ entries are therefore irrelevant and would only serve to corrupt
+ the LinkageMap.
+ @type exclude_pkgs: set
+ @param include_file: The path of a file containing NEEDED entries for
+ a package which does not exist in the vardbapi yet because it is
+ currently being merged.
+ @type include_file: String
+ @param preserve_paths: Libraries preserved by a package instance that
+ is currently being merged. They need to be explicitly passed to the
+ LinkageMap, since they are not registered in the
+ PreservedLibsRegistry yet.
+ @type preserve_paths: set
+ """
+
+ os = _os_merge
+ root = self._root
+ root_len = len(root) - 1
+ self._clear_cache()
+ self._defpath.update(getlibpaths(self._root, env=self._dbapi.settings))
+ libs = self._libs
+ obj_properties = self._obj_properties
+
+ lines = []
+
+ # Data from include_file is processed first so that it
+ # overrides any data from previously installed files.
+ if include_file is not None:
+ for line in grabfile(include_file):
+ lines.append((None, include_file, line))
+
+ aux_keys = [self._needed_aux_key]
+ can_lock = os.access(os.path.dirname(self._dbapi._dbroot), os.W_OK)
+ if can_lock:
+ self._dbapi.lock()
+ try:
+ for cpv in self._dbapi.cpv_all():
+ if exclude_pkgs is not None and cpv in exclude_pkgs:
+ continue
+ needed_file = self._dbapi.getpath(cpv,
+ filename=self._needed_aux_key)
+ for line in self._dbapi.aux_get(cpv, aux_keys)[0].splitlines():
+ lines.append((cpv, needed_file, line))
+ finally:
+ if can_lock:
+ self._dbapi.unlock()
+
+ # have to call readpecoff for preserved libs here as they aren't
+ # registered in NEEDED.PECOFF.1 files
+ plibs = {}
+ if preserve_paths is not None:
+ plibs.update((x, None) for x in preserve_paths)
+ if self._dbapi._plib_registry and \
+ self._dbapi._plib_registry.hasEntries():
+ for cpv, items in \
+ self._dbapi._plib_registry.getPreservedLibs().items():
+ if exclude_pkgs is not None and cpv in exclude_pkgs:
+ # These preserved libs will either be unmerged,
+ # rendering them irrelevant, or they will be
+ # preserved in the replacement package and are
+ # already represented via the preserve_paths
+ # parameter.
+ continue
+ plibs.update((x, cpv) for x in items)
+ if plibs:
+ args = ["readpecoff", self._dbapi.settings.get('CHOST')]
+ args.extend(os.path.join(root, x.lstrip("." + os.sep)) \
+ for x in plibs)
+ try:
+ proc = subprocess.Popen(args, stdout=subprocess.PIPE)
+ except EnvironmentError as e:
+ if e.errno != errno.ENOENT:
+ raise
+ raise CommandNotFound(args[0])
+ else:
+ for l in proc.stdout:
+ try:
+ l = _unicode_decode(l,
+ encoding=_encodings['content'], errors='strict')
+ except UnicodeDecodeError:
+ l = _unicode_decode(l,
+ encoding=_encodings['content'], errors='replace')
+ writemsg_level(_("\nError decoding characters " \
+ "returned from readpecoff: %s\n\n") % (l,),
+ level=logging.ERROR, noiselevel=-1)
+ l = l[3:].rstrip("\n")
+ if not l:
+ continue
+ fields = l.split(";")
+ if len(fields) < 5:
+ writemsg_level(_("\nWrong number of fields " \
+ "returned from readpecoff: %s\n\n") % (l,),
+ level=logging.ERROR, noiselevel=-1)
+ continue
+ fields[1] = fields[1][root_len:]
+ owner = plibs.pop(fields[1], None)
+ lines.append((owner, "readpecoff", ";".join(fields)))
+ proc.wait()
+
+ if plibs:
+ # Preserved libraries that did not appear in the scanelf output.
+ # This is known to happen with statically linked libraries.
+ # Generate dummy lines for these, so we can assume that every
+ # preserved library has an entry in self._obj_properties. This
+ # is important in order to prevent findConsumers from raising
+ # an unwanted KeyError.
+ for x, cpv in plibs.items():
+ lines.append((cpv, "plibs", ";".join(['', x, '', '', ''])))
+
+ # Share identical frozenset instances when available,
+ # in order to conserve memory.
+ frozensets = {}
+
+ for owner, location, l in lines:
+ l = l.rstrip("\n")
+ if not l:
+ continue
+ fields = l.split(";")
+ if len(fields) < 5:
+ writemsg_level(_("\nWrong number of fields " \
+ "in %s: %s\n\n") % (location, l),
+ level=logging.ERROR, noiselevel=-1)
+ continue
+ arch = fields[0]
+ obj = fields[1]
+ soname = fields[2]
+ path = frozenset(normalize_path(x) \
+ for x in filter(None, fields[3].replace(
+ "${ORIGIN}", os.path.dirname(obj)).replace(
+ "$ORIGIN", os.path.dirname(obj)).split(":")))
+ path = frozensets.setdefault(path, path)
+ needed = frozenset(x for x in fields[4].split(",") if x)
+ needed = frozensets.setdefault(needed, needed)
+
+ obj_key = self._obj_key(obj)
+ indexed = True
+ myprops = obj_properties.get(obj_key)
+ if myprops is None:
+ indexed = False
+ myprops = self._obj_properties_class(
+ arch, needed, path, soname, [], owner)
+ obj_properties[obj_key] = myprops
+ # All object paths are added into the obj_properties tuple.
+ myprops.alt_paths.append(obj)
+
+ # Don't index the same file more that once since only one
+ # set of data can be correct and therefore mixing data
+ # may corrupt the index (include_file overrides previously
+ # installed).
+ if indexed:
+ continue
+
+ arch_map = libs.get(arch)
+ if arch_map is None:
+ arch_map = {}
+ libs[arch] = arch_map
+ if soname:
+ soname_map = arch_map.get(soname)
+ if soname_map is None:
+ soname_map = self._soname_map_class(
+ providers=[], consumers=[])
+ arch_map[soname] = soname_map
+ soname_map.providers.append(obj_key)
+ for needed_soname in needed:
+ soname_map = arch_map.get(needed_soname)
+ if soname_map is None:
+ soname_map = self._soname_map_class(
+ providers=[], consumers=[])
+ arch_map[needed_soname] = soname_map
+ soname_map.consumers.append(obj_key)
+
+ for arch, sonames in libs.items():
+ for soname_node in sonames.values():
+ soname_node.providers = tuple(set(soname_node.providers))
+ soname_node.consumers = tuple(set(soname_node.consumers))
diff --git a/lib/portage/util/_dyn_libs/LinkageMapXCoff.py b/lib/portage/util/_dyn_libs/LinkageMapXCoff.py
new file mode 100644
index 000000000..6c4c994b5
--- /dev/null
+++ b/lib/portage/util/_dyn_libs/LinkageMapXCoff.py
@@ -0,0 +1,312 @@
+# Copyright 1998-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+import errno
+import logging
+import subprocess
+
+import portage
+from portage import _encodings
+from portage import _os_merge
+from portage import _unicode_decode
+from portage import _unicode_encode
+from portage.cache.mappings import slot_dict_class
+from portage.exception import CommandNotFound
+from portage.localization import _
+from portage.util import getlibpaths
+from portage.util import grabfile
+from portage.util import normalize_path
+from portage.util import writemsg_level
+from portage.const import EPREFIX, BASH_BINARY
+from portage.util._dyn_libs.LinkageMapELF import LinkageMapELF
+
+class LinkageMapXCoff(LinkageMapELF):
+
+ """Models dynamic linker dependencies."""
+
+ _needed_aux_key = "NEEDED.XCOFF.1"
+
+ class _ObjectKey(LinkageMapELF._ObjectKey):
+
+ def __init__(self, obj, root):
+ LinkageMapELF._ObjectKey.__init__(self, obj, root)
+
+ def _generate_object_key(self, obj, root):
+ """
+ Generate object key for a given object.
+
+ @param object: path to a file
+ @type object: string (example: '/usr/bin/bar')
+ @rtype: 2-tuple of types (long, int) if object exists. string if
+ object does not exist.
+ @return:
+ 1. 2-tuple of object's inode and device from a stat call, if object
+ exists.
+ 2. realpath of object if object does not exist.
+
+ """
+
+ os = _os_merge
+
+ try:
+ _unicode_encode(obj,
+ encoding=_encodings['merge'], errors='strict')
+ except UnicodeEncodeError:
+ # The package appears to have been merged with a
+ # different value of sys.getfilesystemencoding(),
+ # so fall back to utf_8 if appropriate.
+ try:
+ _unicode_encode(obj,
+ encoding=_encodings['fs'], errors='strict')
+ except UnicodeEncodeError:
+ pass
+ else:
+ os = portage.os
+
+ abs_path = os.path.join(root, obj.lstrip(os.sep))
+ try:
+ object_stat = os.stat(abs_path)
+ except OSError:
+ # Use the realpath as the key if the file does not exists on the
+ # filesystem.
+ return os.path.realpath(abs_path)
+ # Return a tuple of the device and inode, as well as the basename,
+ # because of hardlinks (notably for the .libNAME[shr.o] helpers)
+ # the device and inode might be identical.
+ return (object_stat.st_dev, object_stat.st_ino, os.path.basename(abs_path.rstrip(os.sep)))
+
+ class _LibGraphNode(_ObjectKey):
+ __slots__ = ("alt_paths",)
+
+ def __init__(self, key):
+ """
+ Create a _LibGraphNode from an existing _ObjectKey.
+ This re-uses the _key attribute in order to avoid repeating
+ any previous stat calls, which helps to avoid potential race
+ conditions due to inconsistent stat results when the
+ file system is being modified concurrently.
+ """
+ self._key = key._key
+ self.alt_paths = set()
+
+ def __str__(self):
+ return str(sorted(self.alt_paths))
+
+ def rebuild(self, exclude_pkgs=None, include_file=None,
+ preserve_paths=None):
+ """
+ Raises CommandNotFound if there are preserved libs
+ and the scanelf binary is not available.
+
+ @param exclude_pkgs: A set of packages that should be excluded from
+ the LinkageMap, since they are being unmerged and their NEEDED
+ entries are therefore irrelevant and would only serve to corrupt
+ the LinkageMap.
+ @type exclude_pkgs: set
+ @param include_file: The path of a file containing NEEDED entries for
+ a package which does not exist in the vardbapi yet because it is
+ currently being merged.
+ @type include_file: String
+ @param preserve_paths: Libraries preserved by a package instance that
+ is currently being merged. They need to be explicitly passed to the
+ LinkageMap, since they are not registered in the
+ PreservedLibsRegistry yet.
+ @type preserve_paths: set
+ """
+
+ os = _os_merge
+ root = self._root
+ root_len = len(root) - 1
+ self._clear_cache()
+ self._defpath.update(getlibpaths(self._root, env=self._dbapi.settings))
+ libs = self._libs
+ obj_properties = self._obj_properties
+
+ lines = []
+
+ # Data from include_file is processed first so that it
+ # overrides any data from previously installed files.
+ if include_file is not None:
+ for line in grabfile(include_file):
+ lines.append((None, include_file, line))
+
+ aux_keys = [self._needed_aux_key]
+ can_lock = os.access(os.path.dirname(self._dbapi._dbroot), os.W_OK)
+ if can_lock:
+ self._dbapi.lock()
+ try:
+ for cpv in self._dbapi.cpv_all():
+ if exclude_pkgs is not None and cpv in exclude_pkgs:
+ continue
+ needed_file = self._dbapi.getpath(cpv,
+ filename=self._needed_aux_key)
+ for line in self._dbapi.aux_get(cpv, aux_keys)[0].splitlines():
+ lines.append((cpv, needed_file, line))
+ finally:
+ if can_lock:
+ self._dbapi.unlock()
+
+ # have to call scanelf for preserved libs here as they aren't
+ # registered in NEEDED.XCOFF.1 files
+ plibs = {}
+ if preserve_paths is not None:
+ plibs.update((x, None) for x in preserve_paths)
+ if self._dbapi._plib_registry and \
+ self._dbapi._plib_registry.hasEntries():
+ for cpv, items in \
+ self._dbapi._plib_registry.getPreservedLibs().items():
+ if exclude_pkgs is not None and cpv in exclude_pkgs:
+ # These preserved libs will either be unmerged,
+ # rendering them irrelevant, or they will be
+ # preserved in the replacement package and are
+ # already represented via the preserve_paths
+ # parameter.
+ continue
+ plibs.update((x, cpv) for x in items)
+ if plibs:
+ args = [BASH_BINARY , "-c" , ':'
+ + '; for member in "$@"'
+ + '; do archive=${member}'
+ + '; if [[ ${member##*/} == .*"["*"]" ]]'
+ + '; then member=${member%/.*}/${member##*/.}'
+ + '; archive=${member%[*}'
+ + '; fi'
+ + '; member=${member#${archive}}'
+ + '; [[ -r ${archive} ]] || chmod a+r "${archive}"'
+ + '; eval $(aixdll-query "${archive}${member}" FILE MEMBER FLAGS FORMAT RUNPATH DEPLIBS)'
+ + '; [[ -n ${member} ]] && needed=${FILE##*/} || needed='
+ + '; for deplib in ${DEPLIBS}'
+ + '; do eval deplib=${deplib}'
+ + '; if [[ ${deplib} != "." && ${deplib} != ".." ]]'
+ + '; then needed="${needed}${needed:+,}${deplib}"'
+ + '; fi'
+ + '; done'
+ + '; [[ -n ${MEMBER} ]] && MEMBER="[${MEMBER}]"'
+ + '; [[ " ${FLAGS} " == *" SHROBJ "* ]] && soname=${FILE##*/}${MEMBER} || soname='
+ + '; case ${member:+y}:${MEMBER:+y}'
+ # member requested, member found: show shared archive member
+ + ' in y:y) echo "${FORMAT##* }${FORMAT%%-*};${FILE#${ROOT%/}}${MEMBER};${soname};${RUNPATH};${needed}"'
+ # no member requested, member found: show archive
+ + ' ;; :y) echo "${FORMAT##* }${FORMAT%%-*};${FILE#${ROOT%/}};${FILE##*/};;"'
+ # no member requested, no member found: show standalone shared object
+ + ' ;; : ) echo "${FORMAT##* }${FORMAT%%-*};${FILE#${ROOT%/}};${FILE##*/};${RUNPATH};${needed}"'
+ # member requested, no member found: ignore archive replaced by standalone shared object
+ + ' ;; y: )'
+ + ' ;; esac'
+ + '; done'
+ , 'aixdll-query'
+ ]
+ args.extend(os.path.join(root, x.lstrip("." + os.sep)) \
+ for x in plibs)
+ try:
+ proc = subprocess.Popen(args, stdout=subprocess.PIPE)
+ except EnvironmentError as e:
+ if e.errno != errno.ENOENT:
+ raise
+ raise CommandNotFound(args[0])
+ else:
+ for l in proc.stdout:
+ try:
+ l = _unicode_decode(l,
+ encoding=_encodings['content'], errors='strict')
+ except UnicodeDecodeError:
+ l = _unicode_decode(l,
+ encoding=_encodings['content'], errors='replace')
+ writemsg_level(_("\nError decoding characters " \
+ "returned from aixdll-query: %s\n\n") % (l,),
+ level=logging.ERROR, noiselevel=-1)
+ l = l.rstrip("\n")
+ if not l:
+ continue
+ fields = l.split(";")
+ if len(fields) < 5:
+ writemsg_level(_("\nWrong number of fields " \
+ "returned from aixdll-query: %s\n\n") % (l,),
+ level=logging.ERROR, noiselevel=-1)
+ continue
+ fields[1] = fields[1][root_len:]
+ owner = plibs.pop(fields[1], None)
+ lines.append((owner, "aixdll-query", ";".join(fields)))
+ proc.wait()
+ proc.stdout.close()
+
+ # Share identical frozenset instances when available,
+ # in order to conserve memory.
+ frozensets = {}
+
+ for owner, location, l in lines:
+ l = l.rstrip("\n")
+ if not l:
+ continue
+ fields = l.split(";")
+ if len(fields) < 5:
+ writemsg_level(_("\nWrong number of fields " \
+ "in %s: %s\n\n") % (location, l),
+ level=logging.ERROR, noiselevel=-1)
+ continue
+ arch = fields[0]
+
+ def as_contentmember(obj):
+ if obj.endswith("]"):
+ if obj.find("/") >= 0:
+ if obj[obj.rfind("/")+1] == ".":
+ return obj
+ return obj[:obj.rfind("/")] + "/." + obj[obj.rfind("/")+1:]
+ if obj[0] == ".":
+ return obj
+ return "." + obj
+ return obj
+
+ obj = as_contentmember(fields[1])
+ soname = as_contentmember(fields[2])
+ path = frozenset(normalize_path(x) \
+ for x in filter(None, fields[3].replace(
+ "${ORIGIN}", os.path.dirname(obj)).replace(
+ "$ORIGIN", os.path.dirname(obj)).split(":")))
+ path = frozensets.setdefault(path, path)
+ needed = frozenset(as_contentmember(x) for x in fields[4].split(",") if x)
+ needed = frozensets.setdefault(needed, needed)
+
+ obj_key = self._obj_key(obj)
+ indexed = True
+ myprops = obj_properties.get(obj_key)
+ if myprops is None:
+ indexed = False
+ myprops = self._obj_properties_class(
+ arch, needed, path, soname, [], owner)
+ obj_properties[obj_key] = myprops
+ # All object paths are added into the obj_properties tuple.
+ myprops.alt_paths.append(obj)
+
+ # Don't index the same file more that once since only one
+ # set of data can be correct and therefore mixing data
+ # may corrupt the index (include_file overrides previously
+ # installed).
+ if indexed:
+ continue
+
+ arch_map = libs.get(arch)
+ if arch_map is None:
+ arch_map = {}
+ libs[arch] = arch_map
+ if soname:
+ soname_map = arch_map.get(soname)
+ if soname_map is None:
+ soname_map = self._soname_map_class(
+ providers=[], consumers=[])
+ arch_map[soname] = soname_map
+ soname_map.providers.append(obj_key)
+ for needed_soname in needed:
+ soname_map = arch_map.get(needed_soname)
+ if soname_map is None:
+ soname_map = self._soname_map_class(
+ providers=[], consumers=[])
+ arch_map[needed_soname] = soname_map
+ soname_map.consumers.append(obj_key)
+
+ for arch, sonames in libs.items():
+ for soname_node in sonames.values():
+ soname_node.providers = tuple(set(soname_node.providers))
+ soname_node.consumers = tuple(set(soname_node.consumers))
+
+ pass
diff --git a/lib/portage/util/_info_files.py b/lib/portage/util/_info_files.py
index fabf74b0f..de44b0fdc 100644
--- a/lib/portage/util/_info_files.py
+++ b/lib/portage/util/_info_files.py
@@ -9,16 +9,17 @@ import subprocess
import portage
from portage import os
+from portage.const import EPREFIX
def chk_updated_info_files(root, infodirs, prev_mtimes):
- if os.path.exists("/usr/bin/install-info"):
+ if os.path.exists(EPREFIX + "/usr/bin/install-info"):
out = portage.output.EOutput()
regen_infodirs = []
for z in infodirs:
if z == '':
continue
- inforoot = portage.util.normalize_path(root + z)
+ inforoot = portage.util.normalize_path(root + EPREFIX + z)
if os.path.isdir(inforoot) and \
not [x for x in os.listdir(inforoot) \
if x.startswith('.keepinfodir')]:
@@ -78,7 +79,7 @@ def chk_updated_info_files(root, infodirs, prev_mtimes):
processed_count += 1
try:
proc = subprocess.Popen(
- ['/usr/bin/install-info',
+ ['%s/usr/bin/install-info' % EPREFIX,
'--dir-file=%s' % os.path.join(inforoot, "dir"),
os.path.join(inforoot, x)],
env=dict(os.environ, LANG="C", LANGUAGE="C"),
diff --git a/lib/portage/util/_pty.py b/lib/portage/util/_pty.py
index 11c8b92af..a92f57543 100644
--- a/lib/portage/util/_pty.py
+++ b/lib/portage/util/_pty.py
@@ -9,12 +9,12 @@ from portage import os
from portage.output import get_term_size, set_term_size
from portage.util import writemsg
-# Disable the use of openpty on Solaris as it seems Python's openpty
-# implementation doesn't play nice on Solaris with Portage's
-# behaviour causing hangs/deadlocks.
+# Disable the use of openpty on Solaris (and others) as it seems Python's
+# openpty implementation doesn't play nice with Portage's behaviour,
+# causing hangs/deadlocks.
# Additional note for the future: on Interix, pipes do NOT work, so
# _disable_openpty on Interix must *never* be True
-_disable_openpty = platform.system() in ("SunOS",)
+_disable_openpty = platform.system() in ("AIX","FreeMiNT","HP-UX","SunOS",)
_fbsd_test_pty = platform.system() == 'FreeBSD'
diff --git a/lib/portage/util/env_update.py b/lib/portage/util/env_update.py
index 032101043..a69114d80 100644
--- a/lib/portage/util/env_update.py
+++ b/lib/portage/util/env_update.py
@@ -88,7 +88,7 @@ def _env_update(makelinks, target_root, prev_mtimes, contents, env,
else:
settings = env
- eprefix = settings.get("EPREFIX", "")
+ eprefix = settings.get("EPREFIX", portage.const.EPREFIX)
eprefix_lstrip = eprefix.lstrip(os.sep)
eroot = normalize_path(os.path.join(target_root, eprefix_lstrip)).rstrip(os.sep) + os.sep
envd_dir = os.path.join(eroot, "etc", "env.d")
@@ -340,8 +340,8 @@ def _env_update(makelinks, target_root, prev_mtimes, contents, env,
penvnotice = "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n"
penvnotice += "# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES\n"
cenvnotice = penvnotice[:]
- penvnotice += "# GO INTO /etc/profile NOT /etc/profile.env\n\n"
- cenvnotice += "# GO INTO /etc/csh.cshrc NOT /etc/csh.env\n\n"
+ penvnotice += "# GO INTO " + eprefix + "/etc/profile NOT /etc/profile.env\n\n"
+ cenvnotice += "# GO INTO " + eprefix + "/etc/csh.cshrc NOT /etc/csh.env\n\n"
#create /etc/profile.env for bash support
outfile = atomic_ofstream(os.path.join(eroot, "etc", "profile.env"))
diff --git a/lib/portage/versions.py b/lib/portage/versions.py
index 0c21373cc..0b1d50e7c 100644
--- a/lib/portage/versions.py
+++ b/lib/portage/versions.py
@@ -51,7 +51,9 @@ _pkg = {
}
_v = r'(\d+)((\.\d+)*)([a-z]?)((_(pre|p|beta|alpha|rc)\d*)*)'
-_rev = r'\d+'
+# PREFIX_LOCAL hack: -r(\d+) -> -r(\d+|\d+\.\d+) (see below)
+_rev = r'(\d+|\d+\.\d+)'
+# END_PREFIX_LOCAL
_vr = _v + '(-r(' + _rev + '))?'
_cp = {
@@ -250,15 +252,47 @@ def vercmp(ver1, ver2, silent=1):
if rval:
return rval
- # the suffix part is equal to, so finally check the revision
+ # PREFIX_LOCAL
+ # The suffix part is equal too, so finally check the revision
+ # Prefix hack: historically a revision starting with 0 was an
+ # 'inter-revision', which means that it is possible to create
+ # revisions on revisions. An example is -r01.1 which is the
+ # first revision of -r1. Note that a period (.) is used to
+ # separate the real revision and the secondary revision number.
+ # In the current state, the leading 0 is no longer used, and
+ # versions just can have a dot, which means the version is an
+ # inter-revision.
+ # This trick is in use to allow revision bumps in ebuilds synced
+ # from the main tree for Prefix changes, while still staying in
+ # the main tree versioning scheme. As such it can be used in
+ # any other overlay where ebuilds from the another tree are
+ # shadowed.
if match1.group(9):
- r1 = int(match1.group(9))
+ if '.' in match1.group(9):
+ t = match1.group(9).split(".")
+ r1 = int(t[0])
+ r3 = int(t[1])
+ else:
+ r1 = int(match1.group(9))
+ r3 = 0
else:
r1 = 0
+ r3 = 0
if match2.group(9):
- r2 = int(match2.group(9))
+ if '.' in match2.group(9):
+ t = match2.group(9).split(".")
+ r2 = int(t[0])
+ r4 = int(t[1])
+ else:
+ r2 = int(match2.group(9))
+ r4 = 0
+ # END_PREFIX_LOCAL
else:
r2 = 0
+ r4 = 0
+ if r1 == r2 and (r3 != 0 or r4 != 0):
+ r1 = r3
+ r2 = r4
rval = (r1 > r2) - (r1 < r2)
return rval
diff --git a/man/Makefile.am b/man/Makefile.am
new file mode 100644
index 000000000..4034c99ba
--- /dev/null
+++ b/man/Makefile.am
@@ -0,0 +1,17 @@
+SHELL = @PORTAGE_BASH@
+
+man_MANS = \
+ color.map.5 \
+ dispatch-conf.1 \
+ ebuild.1 \
+ ebuild.5 \
+ egencache.1 \
+ emaint.1 \
+ emerge.1 \
+ env-update.1 \
+ etc-update.1 \
+ make.conf.5 \
+ portage.5 \
+ quickpkg.1
+
+EXTRA_DIST = $(man_MANS)
diff --git a/man/ebuild.5 b/man/ebuild.5
index e955907f7..4ca3f3a15 100644
--- a/man/ebuild.5
+++ b/man/ebuild.5
@@ -852,6 +852,12 @@ characters.
This variable is intended to be used on files of binary packages which ignore
CFLAGS, CXXFLAGS, FFLAGS, FCFLAGS, and LDFLAGS variables.
.TP
+.B QA_IGNORE_INSTALL_NAME_FILES
+This should contain a list of file names (without path) that should be
+ignored in the install_name check. That is, if these files point to
+something not available in the image directory or live filesystem, these
+files are ignored, albeit being broken.
+.TP
.B QA_MULTILIB_PATHS
This should contain a list of file paths, relative to the image directory, of
files that should be ignored for the multilib\-strict checks.
diff --git a/man/emerge.1 b/man/emerge.1
index 28b7f79f5..aa28ab337 100644
--- a/man/emerge.1
+++ b/man/emerge.1
@@ -1410,6 +1410,12 @@ add this to \fBmake.conf\fR(5):
Tools such as dispatch\-conf, cfg\-update, and etc\-update are also available
to aid in the merging of these files. They provide interactive merging and can
auto\-merge trivial changes.
+.LP
+When an offset prefix (\fBEPREFIX\fR) is active, all paths in
+\fBCONFIG_PROTECT\fR and \fBCONFIG_PROTECT_MASK\fR are prefixed with the
+offset by Portage before they are considered. Hence, these paths never
+contain the offset prefix, and the variables can be defined in
+offset-unaware locations, such as the profiles.
.SH "REPORTING BUGS"
Please report any bugs you encounter through our website:
.LP
@@ -1429,6 +1435,7 @@ Marius Mauch <genone@gentoo.org>
Jason Stubbs <jstubbs@gentoo.org>
Brian Harring <ferringb@gmail.com>
Zac Medico <zmedico@gentoo.org>
+Fabian Groffen <grobian@gentoo.org>
Arfrever Frehtes Taifersar Arahesis <arfrever@apache.org>
.fi
.SH "FILES"
diff --git a/man/make.conf.5 b/man/make.conf.5
index a3bd662ae..ab00cb7d7 100644
--- a/man/make.conf.5
+++ b/man/make.conf.5
@@ -193,6 +193,9 @@ Defaults to "/lib/modules/* *.py[co]".
All files and/or directories that are defined here will have "config file
protection" enabled for them. See the \fBCONFIGURATION FILES\fR section
of \fBemerge\fR(1) for more information.
+Note that if an offset prefix (\fBEPREFIX\fR) is activated, all paths defined
+in \fBCONFIG_PROTECT\fR are prefixed by Portage with the offset before
+they are used.
.TP
\fBCONFIG_PROTECT_MASK\fR = \fI[space delimited list of files and/or \
directories]\fR
@@ -613,6 +616,9 @@ dependencies.
.TP
.B sandbox
Enable sandbox\-ing when running \fBemerge\fR(1) and \fBebuild\fR(1).
+On Mac OS X platforms that have /usr/bin/sandbox-exec available (10.5
+and later), this particular sandbox implementation is used instead of
+sys-apps/sandbox.
.TP
.B sesandbox
Enable SELinux sandbox\-ing. Do not toggle this \fBFEATURE\fR yourself.
diff --git a/misc/emerge-delta-webrsync b/misc/emerge-delta-webrsync
index 082e15e52..d459a2386 100755
--- a/misc/emerge-delta-webrsync
+++ b/misc/emerge-delta-webrsync
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@PORTAGE_BASH@
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# Author: Brian Harring <ferringb@gentoo.org>, karltk@gentoo.org originally.
diff --git a/runtests b/runtests
index 11c317dff..15cc0bc77 100755
--- a/runtests
+++ b/runtests
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# Copyright 2010-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
#
diff --git a/subst-install.in b/subst-install.in
new file mode 100644
index 000000000..e9f375d76
--- /dev/null
+++ b/subst-install.in
@@ -0,0 +1,74 @@
+#!@PORTAGE_BASH@
+
+# for expansion below we need some things to be defined
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+
+# For bug #279550 we have to do some nasty trick to make sure that sed
+# doesn't strip the backslash in the replacement value (because it can
+# be a backreference) and hence escape those. Eventually in strings we
+# need to escape the backslash too, such that the single backslash
+# doesn't get lost when considered an invalid escape
+rootuser='@rootuser@'
+portagegroup='@portagegroup@'
+portageuser='@portageuser@'
+rootuser=${rootuser//\\/\\\\}
+portagegroup=${portagegroup//\\/\\\\\\\\}
+portageuser=${portageuser//\\/\\\\\\\\}
+
+# there are many ways to do this all dynamic, but we only care for raw
+# speed here, so let configure fill in this list and be done with it
+at='@'
+sedexp=(
+ -e "s,${at}EXTRA_PATH${at},@EXTRA_PATH@,g"
+ -e "s,${at}PORTAGE_BASE${at},@PORTAGE_BASE@,g"
+ -e "s,${at}PORTAGE_BASH${at},@PORTAGE_BASH@,g"
+ -e "s,${at}PORTAGE_EPREFIX${at},@PORTAGE_EPREFIX@,g"
+ -e "s,${at}PORTAGE_MV${at},@PORTAGE_MV@,g"
+ -e "s,${at}PREFIX_PORTAGE_PYTHON${at},@PREFIX_PORTAGE_PYTHON@,g"
+ -e "s,${at}datadir${at},@datadir@,g"
+ -e "s,${at}portagegroup${at},${portagegroup},g"
+ -e "s,${at}portageuser${at},${portageuser},g"
+ -e "s,${at}rootgid${at},@rootgid@,g"
+ -e "s,${at}rootuid${at},@rootuid@,g"
+ -e "s,${at}rootuser${at},${rootuser},g"
+ -e "s,${at}sysconfdir${at},@sysconfdir@,g"
+)
+
+sources=( )
+target=
+args=( "$@" )
+
+while [[ ${#@} != 0 ]] ; do
+ case "$1" in
+ -t)
+ [[ -n ${target} ]] && sources=( "${sources[@]}" "${target##*/}" )
+ shift
+ target=":${1}"
+ ;;
+ -*)
+ shift
+ ;;
+ *)
+ if [[ -z ${target} ]] ; then
+ target="${1}"
+ elif [[ ${target} != ":"* ]] ; then
+ sources=( "${sources[@]}" "${target##*/}" )
+ target="${1}"
+ else
+ sources=( "${sources[@]}" "${1##*/}" )
+ fi
+ ;;
+ esac
+ shift
+done
+
+target=${target#:}
+INSTALL="@INSTALL@"
+echo @INSTALL_DATA@ "${args[@]}"
+if [[ ! -d ${target} ]] ; then
+ # either install will die, or it was just a single file copy
+ @INSTALL_DATA@ "${args[@]}" && sed -i "${sedexp[@]}" "${target}"
+else
+ @INSTALL_DATA@ "${args[@]}" && sed -i "${sedexp[@]}" "${sources[@]/#/${target}/}"
+fi
diff --git a/tabcheck.py b/tabcheck.py
index a28ad93d9..fe5227ca7 100755
--- a/tabcheck.py
+++ b/tabcheck.py
@@ -1,6 +1,7 @@
-#!/usr/bin/python -b
+#!/usr/bin/env python
import tabnanny,sys
for x in sys.argv:
+ print ("Tabchecking " + x)
tabnanny.check(x)
diff --git a/tarball.sh b/tarball.sh
new file mode 100755
index 000000000..e67e7244c
--- /dev/null
+++ b/tarball.sh
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+
+if [ -z "$1" ]; then
+ echo
+ echo "You need to have the version specified."
+ echo "e.g.: $0 2.0.39-r37"
+ echo
+ exit 0
+fi
+
+export PKG="prefix-portage"
+export TMP="/var/tmp"
+export V="$1"
+export DEST="${TMP}/${PKG}-${V}"
+
+if [[ -e ${DEST} ]]; then
+ echo ${DEST} already exists, please remove first
+ exit 1
+fi
+
+./tabcheck.py $(
+ find ./ -name .git -o -name .hg -prune -o -type f ! -name '*.py' -print \
+ | xargs grep -l "#\!@PREFIX_PORTAGE_PYTHON@" \
+ | grep -v "^\./repoman/"
+ find ./ -name .git -o -name .hg -prune -o -type f -name '*.py' -print \
+ | grep -v "^\./repoman/"
+
+)
+
+install -d -m0755 ${DEST}
+rsync -a --exclude='.git' --exclude='.hg' --exclude="repoman/" . ${DEST}
+sed -i -e '/^VERSION\s*=/s/^.*$/VERSION = "'${V}-prefix'"/' \
+ ${DEST}/lib/portage/__init__.py
+sed -i -e "/version = /s/'[^']\+'/'${V}-prefix'/" ${DEST}/setup.py
+sed -i -e "1s/VERSION/${V}-prefix/" ${DEST}/man/{,ru/}*.[15]
+sed -i -e "s/@version@/${V}/" ${DEST}/configure.ac
+
+cd ${DEST}
+find -name '*~' | xargs --no-run-if-empty rm -f
+find -name '*.pyc' | xargs --no-run-if-empty rm -f
+find -name '*.pyo' | xargs --no-run-if-empty rm -f
+cd $TMP
+rm -f \
+ ${PKG}-${V}/bin/emerge.py \
+ ${PKG}-${V}/bin/{pmake,sandbox} \
+ ${PKG}-${V}/{bin,lib}/'.#'* \
+ ${PKG}-${V}/{bin,lib}/*.{orig,diff} \
+ ${PKG}-${V}/{bin,lib}/*.py[oc]
+cd $TMP/${PKG}-${V}
+chmod a+x autogen.sh && ./autogen.sh || { echo "autogen failed!"; exit -1; };
+rm -f autogen.sh tabcheck.py tarball.sh commit
+cd $TMP
+tar --numeric-owner -jcf ${TMP}/${PKG}-${V}.tar.bz2 ${PKG}-${V}
+rm -R ${TMP}/${PKG}-${V}
+ls -la ${TMP}/${PKG}-${V}.tar.bz2
diff --git a/travis.sh b/travis.sh
new file mode 100755
index 000000000..bcb95a9cb
--- /dev/null
+++ b/travis.sh
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+
+# this script runs the tests as Travis would do (.travis.yml) and can be
+# used to test the Prefix branch of portage on a non-Prefix system
+
+: ${TMPDIR=/var/tmp}
+
+HERE=$(dirname $(realpath ${BASH_SOURCE[0]}))
+REPO=${HERE##*/}.$$
+
+cd ${TMPDIR}
+git clone ${HERE} ${REPO}
+
+cd ${REPO}
+printf "[build_ext]\nportage-ext-modules=true" >> setup.cfg
+find . -type f -exec \
+ sed -e "s|@PORTAGE_EPREFIX@||" \
+ -e "s|@PORTAGE_BASE@|${PWD}|" \
+ -e "s|@PORTAGE_MV@|$(type -P mv)|" \
+ -e "s|@PORTAGE_BASH@|$(type -P bash)|" \
+ -e "s|@PREFIX_PORTAGE_PYTHON@|$(type -P python)|" \
+ -e "s|@EXTRA_PATH@|${EPREFIX}/usr/sbin:${EPREFIX}/sbin|" \
+ -e "s|@portagegroup@|$(id -gn)|" \
+ -e "s|@portageuser@|$(id -un)|" \
+ -e "s|@rootuser@|$(id -un)|" \
+ -e "s|@rootuid@|$(id -u)|" \
+ -e "s|@rootgid@|$(id -g)|" \
+ -e "s|@sysconfdir@|${EPREFIX}/etc|" \
+ -i '{}' +
+unset EPREFIX
+./setup.py test