From 5849a50842567fc280df5a9a4efa2a61fbca34bb Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Thu, 12 Mar 2009 20:07:48 +0000 Subject: [PATCH] Merged from trunk -r13063:13091 | 13064 | Use ${x##*/} instead of calling basename. | | zmedico | | | 13065 | Bug #262096 - Add separate eerror, elog, eqawarn, and ewarn | | zmedico | binaries for use by non-bash programs running inside the | | | ebuild environment, such as sandbox. | | 13066 | Also add an einfo binary. | | zmedico | | | 13067 | Use posix compatible find -perm arguments. Thanks to | | zmedico | Timothy Redaelli for reporting. | | 13068 | When translating portage uid/gid to root uid/gid after | | zmedico | src_install on FreeBSD, temporarily remove all file flags | | | inside $D in order to avoid EPERM errors. Thanks to Timothy | | | Redaelli for reporting. | | 13069 | Make dyn_clean ignore FEATURES=keepwork when [[ | | zmedico | $EMERGE_FROM = binary ]] and remove shutil.rmtree() call | | | from Binpkg._clean_exit() since dyn_clean is guaranteed to | | | do a full clean now. | | 13070 | Bug #261992 - Inside Binpkg._prefetch_exit(), avoid | | zmedico | potention issues with shutil.rmtree() by just doing a | | | minimal cleanup. | | 13071 | Bug #261992 - Replace the EbuildBuildDir.clean() method | | zmedico | with a clean_log() method since log cleanup is all that's | | | currently needed and shutil.rmtree() can fail with | | | "OSError: [Errno 36] File name too long" due to strange | | | file names, or on FreeBSD it can fail with EPERM due to | | | file flags in $D. | | 13072 | Update docstring for EbuildBuildDir.clean_log(). | | zmedico | | | 13088 | Bug #261670 - Automatically revert the CHOST metadata to | | zmedico | the initial value after src_install, in case the ebuild has | | | changed it. | | 13090 | cleanup sandbox env var handling -- make sure we dont | | SpankMan | insert empty : sections and avoid unnecessary eval usage | | 13091 | Filter _sb_append_var in save_ebuild_env(). | | zmedico | | svn path=/main/branches/prefix/; revision=13099 --- bin/ebuild-helpers/doexe | 2 +- bin/ebuild-helpers/eerror | 1 + bin/ebuild-helpers/einfo | 1 + bin/ebuild-helpers/elog | 8 +++++ bin/ebuild-helpers/eqawarn | 1 + bin/ebuild-helpers/ewarn | 1 + bin/ebuild.sh | 61 +++++++++++++++++++------------------- bin/isolated-functions.sh | 2 +- bin/misc-functions.sh | 4 +-- pym/_emerge/__init__.py | 39 +++++++++--------------- pym/portage/__init__.py | 29 ++++++++++++++++++ 11 files changed, 89 insertions(+), 60 deletions(-) create mode 120000 bin/ebuild-helpers/eerror create mode 120000 bin/ebuild-helpers/einfo create mode 100755 bin/ebuild-helpers/elog create mode 120000 bin/ebuild-helpers/eqawarn create mode 120000 bin/ebuild-helpers/ewarn diff --git a/bin/ebuild-helpers/doexe b/bin/ebuild-helpers/doexe index bd278e52e..34818ccb1 100755 --- a/bin/ebuild-helpers/doexe +++ b/bin/ebuild-helpers/doexe @@ -17,7 +17,7 @@ fi for x in "$@" ; do if [ -L "${x}" ] ; then cp "${x}" "${T}" - mysrc="${T}"/$(basename "${x}") + mysrc="$T/${x##*/}" elif [ -d "${x}" ] ; then vecho "doexe: warning, skipping directory ${x}" continue diff --git a/bin/ebuild-helpers/eerror b/bin/ebuild-helpers/eerror new file mode 120000 index 000000000..a403c7588 --- /dev/null +++ b/bin/ebuild-helpers/eerror @@ -0,0 +1 @@ +elog \ No newline at end of file diff --git a/bin/ebuild-helpers/einfo b/bin/ebuild-helpers/einfo new file mode 120000 index 000000000..a403c7588 --- /dev/null +++ b/bin/ebuild-helpers/einfo @@ -0,0 +1 @@ +elog \ No newline at end of file diff --git a/bin/ebuild-helpers/elog b/bin/ebuild-helpers/elog new file mode 100755 index 000000000..2e2674b52 --- /dev/null +++ b/bin/ebuild-helpers/elog @@ -0,0 +1,8 @@ +#!@PORTAGE_BASH@ +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + +source "${PORTAGE_BIN_PATH:-${EPREFIX}/usr/lib/portage/bin}"/isolated-functions.sh + +${0##*/} "$@" diff --git a/bin/ebuild-helpers/eqawarn b/bin/ebuild-helpers/eqawarn new file mode 120000 index 000000000..a403c7588 --- /dev/null +++ b/bin/ebuild-helpers/eqawarn @@ -0,0 +1 @@ +elog \ No newline at end of file diff --git a/bin/ebuild-helpers/ewarn b/bin/ebuild-helpers/ewarn new file mode 120000 index 000000000..a403c7588 --- /dev/null +++ b/bin/ebuild-helpers/ewarn @@ -0,0 +1 @@ +elog \ No newline at end of file diff --git a/bin/ebuild.sh b/bin/ebuild.sh index e2935d52a..790b24571 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -6,10 +6,9 @@ PORTAGE_BIN_PATH="${PORTAGE_BIN_PATH:-@PORTAGE_BASE@/bin}" PORTAGE_PYM_PATH="${PORTAGE_PYM_PATH:-@PORTAGE_BASE@/pym}" -SANDBOX_PREDICT="${SANDBOX_PREDICT}:/proc/self/maps:/dev/console:/dev/random" -export SANDBOX_PREDICT -export SANDBOX_WRITE="${SANDBOX_WRITE}:/dev/shm:/dev/stdout:/dev/stderr:${PORTAGE_TMPDIR}" -export SANDBOX_READ="${SANDBOX_READ}:/:/dev/shm:/dev/stdin:${PORTAGE_TMPDIR}" +export SANDBOX_PREDICT="${SANDBOX_PREDICT:+${SANDBOX_PREDICT}:}/proc/self/maps:/dev/console:/dev/random" +export SANDBOX_WRITE="${SANDBOX_WRITE:+${SANDBOX_WRITE}:}/dev/shm:/dev/stdout:/dev/stderr:${PORTAGE_TMPDIR}" +export SANDBOX_READ="${SANDBOX_READ:+${SANDBOX_READ}:}/:/dev/shm:/dev/stdin:${PORTAGE_TMPDIR}" # Don't use sandbox's BASH_ENV for new shells because it does # 'source /etc/profile' which can interfere with the build # environment by modifying our PATH. @@ -85,25 +84,19 @@ source "${PORTAGE_BIN_PATH}/isolated-functions.sh" &>/dev/null export SANDBOX_ON="0" # sandbox support functions; defined prior to profile.bashrc srcing, since the profile might need to add a default exception (/usr/lib64/conftest fex) -addread() { - [[ -z $1 || -n $2 ]] && die "Usage: addread " - export SANDBOX_READ="$SANDBOX_READ:$1" -} - -addwrite() { - [[ -z $1 || -n $2 ]] && die "Usage: addwrite " - export SANDBOX_WRITE="$SANDBOX_WRITE:$1" -} - -adddeny() { - [[ -z $1 || -n $2 ]] && die "Usage: adddeny " - export SANDBOX_DENY="$SANDBOX_DENY:$1" -} - -addpredict() { - [[ -z $1 || -n $2 ]] && die "Usage: addpredict " - export SANDBOX_PREDICT="$SANDBOX_PREDICT:$1" -} +_sb_append_var() { + local _v=$1 ; shift + local var="SANDBOX_${_v}" + [[ -z $1 || -n $2 ]] && die "Usage: add$(echo ${_v} | LC_ALL=C tr :upper: :lower:) " + export ${var}="${!var:+${!var}:}$1" +} +# bash-4 version: +# local var="SANDBOX_${1^^}" +# addread() { _sb_append_var ${0#add} "$@" ; } +addread() { _sb_append_var READ "$@" ; } +addwrite() { _sb_append_var WRITE "$@" ; } +adddeny() { _sb_append_var DENY "$@" ; } +addpredict() { _sb_append_var PREDICT "$@" ; } lchown() { chown -h "$@" @@ -721,11 +714,12 @@ dyn_clean() { rm -rf "${PORTAGE_BUILDDIR}/image" "${PORTAGE_BUILDDIR}/homedir" rm -f "${PORTAGE_BUILDDIR}/.installed" - if ! hasq keeptemp $FEATURES && ! hasq keepwork $FEATURES ; then + if [[ $EMERGE_FROM = binary ]] || \ + ! hasq keeptemp $FEATURES && ! hasq keepwork $FEATURES ; then rm -rf "${T}" fi - if ! hasq keepwork $FEATURES; then + if [[ $EMERGE_FROM = binary ]] || ! hasq keepwork $FEATURES; then rm -f "$PORTAGE_BUILDDIR"/.{exit_status,logid,unpacked,prepared} \ "$PORTAGE_BUILDDIR"/.{configured,compiled,tested,packaged} @@ -958,13 +952,14 @@ dyn_test() { ewarn "Skipping make test/check due to ebuild restriction." vecho ">>> Test phase [explicitly disabled]: ${CATEGORY}/${PF}" else + local save_sp=${SANDBOX_PREDICT} addpredict / ebuild_phase pre_src_test ebuild_phase src_test touch "$PORTAGE_BUILDDIR/.tested" || \ die "Failed to 'touch .tested' in $PORTAGE_BUILDDIR" ebuild_phase post_src_test - SANDBOX_PREDICT="${SANDBOX_PREDICT%:/}" + SANDBOX_PREDICT=${save_sp} fi trap - SIGINT SIGQUIT @@ -1844,7 +1839,7 @@ if ! hasq "$EBUILD_PHASE" clean cleanrm depend && \ die "error processing environment" # Colon separated SANDBOX_* variables need to be cumulative. for x in SANDBOX_DENY SANDBOX_READ SANDBOX_PREDICT SANDBOX_WRITE ; do - eval PORTAGE_${x}=\${!x} + export PORTAGE_${x}=${!x} done PORTAGE_SANDBOX_ON=${SANDBOX_ON} export SANDBOX_ON=1 @@ -1856,11 +1851,15 @@ if ! hasq "$EBUILD_PHASE" clean cleanrm depend && \ # until we've merged them with our current values. export SANDBOX_ON=0 for x in SANDBOX_DENY SANDBOX_PREDICT SANDBOX_READ SANDBOX_WRITE ; do - eval y=\${PORTAGE_${x}} - if [ "${y}" != "${!x}" ] ; then - eval export ${x}=\"$(echo -n "${y}:${!x}" | tr ":" "\0" | \ - sort -z -u | tr "\0" ":")\" + y="PORTAGE_${x}" + if [ -z "${!x}" ] ; then + export ${x}=${!y} + elif [ -n "${!y}" ] && [ "${!y}" != "${!x}" ] ; then + # filter out dupes + export ${x}=$(printf "${!y}:${!x}" | tr ":" "\0" | \ + sort -z -u | tr "\0" ":") fi + export ${x}=${!x%:} unset PORTAGE_${x} done unset x y diff --git a/bin/isolated-functions.sh b/bin/isolated-functions.sh index b3256452c..839b8da28 100755 --- a/bin/isolated-functions.sh +++ b/bin/isolated-functions.sh @@ -503,7 +503,7 @@ save_ebuild_env() { esyslog einfo einfon ewarn eerror ebegin _eend eend KV_major \ KV_minor KV_micro KV_to_int get_KV unset_colors set_colors has \ hasg hasgq hasv hasq qa_source qa_call \ - addread addwrite adddeny addpredict \ + addread addwrite adddeny addpredict _sb_append_var \ lchown lchgrp esyslog use usev useq has_version portageq \ best_version use_with use_enable register_die_hook check_KV \ keepdir unpack strip_duplicate_slashes econf einstall \ diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh index fa4b77b1e..5ef5f53b4 100644 --- a/bin/misc-functions.sh +++ b/bin/misc-functions.sh @@ -75,8 +75,8 @@ install_qa_check() { f=$(scanelf -qyRF '%r %p' "${ED}" | grep -E "(${PORTAGE_BUILDDIR}|: |::|^:|^ )") # Reject set*id binaries with $ORIGIN in RPATH #260331 x=$( - find "${D}" -type f -perm /6000 -print0 | xargs -0 \ - scanelf -qyRF '%r %p' | grep '$ORIGIN' + find "${D}" -type f \( -perm -u+s -o -perm -g+s \) -print0 | \ + xargs -0 scanelf -qyRF '%r %p' | grep '$ORIGIN' ) if [[ -n ${f}${x} ]] ; then vecho -ne '\a\n' diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index eda2ca394..54ea57340 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -2534,7 +2534,7 @@ class EbuildFetcher(SpawnProcess): if not self.prefetch: self._build_dir = EbuildBuildDir(pkg=self.pkg, settings=settings) self._build_dir.lock() - self._build_dir.clean() + self._build_dir.clean_log() portage.prepare_build_dirs(self.pkg.root, self._build_dir.settings, 0) if self.logfile is None: self.logfile = settings.get("PORTAGE_LOG_FILE") @@ -2605,7 +2605,7 @@ class EbuildFetcher(SpawnProcess): portage.elog.elog_process(self.pkg.cpv, self._build_dir.settings) features = self._build_dir.settings.features if self.returncode == os.EX_OK: - self._build_dir.clean() + self._build_dir.clean_log() self._build_dir.unlock() self.config_pool.deallocate(self._build_dir.settings) self._build_dir = None @@ -2660,18 +2660,15 @@ class EbuildBuildDir(SlotObject): if catdir_lock is not None: portage.locks.unlockdir(catdir_lock) - def clean(self): - """Uses shutil.rmtree() rather than spawning a 'clean' phase. Disabled - by keepwork or keeptemp in FEATURES.""" + def clean_log(self): + """Discard existing log.""" settings = self.settings - features = settings.features - if not ("keepwork" in features or "keeptemp" in features): + + for x in ('.logid', 'temp/build.log'): try: - shutil.rmtree(settings["PORTAGE_BUILDDIR"]) - except EnvironmentError, e: - if e.errno != errno.ENOENT: - raise - del e + os.unlink(os.path.join(settings["PORTAGE_BUILDDIR"], x)) + except OSError: + pass def unlock(self): if self._lock_obj is None: @@ -3219,6 +3216,7 @@ class EbuildPhase(CompositeTask): settings = self.settings if self.phase == "install": + portage._post_src_install_chost_fix(settings) portage._post_src_install_uid_fix(settings) post_phase_cmds = self._post_phase_cmds.get(self.phase) @@ -3440,12 +3438,10 @@ class Binpkg(CompositeTask): pkg_count = self.pkg_count if not (self.opts.pretend or self.opts.fetchonly): self._build_dir.lock() - try: - shutil.rmtree(self._build_dir.dir_path) - except EnvironmentError, e: - if e.errno != errno.ENOENT: - raise - del e + # If necessary, discard old log so that we don't + # append to it. + self._build_dir.clean_log() + # Initialze PORTAGE_LOG_FILE. portage.prepare_build_dirs(self.settings["ROOT"], self.settings, 1) fetcher = BinpkgFetcher(background=self.background, logfile=self.settings.get("PORTAGE_LOG_FILE"), pkg=self.pkg, @@ -3537,13 +3533,6 @@ class Binpkg(CompositeTask): dir_path = self._build_dir.dir_path - try: - shutil.rmtree(dir_path) - except (IOError, OSError), e: - if e.errno != errno.ENOENT: - raise - del e - infloc = self._infloc pkg = self.pkg pkg_path = self._pkg_path diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 3527fa7de..2a5248ff8 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -4743,6 +4743,7 @@ def spawnebuild(mydo, actionmap, mysettings, debug, alwaysdep=0, if mydo == "install": _check_build_log(mysettings) if phase_retval == os.EX_OK: + _post_src_install_chost_fix(mysettings) phase_retval = _post_src_install_checks(mysettings) if mydo == "test" and phase_retval != os.EX_OK and \ @@ -4893,6 +4894,17 @@ def _check_build_log(mysettings, out=None): msg.extend("\t" + line for line in make_jobserver) _eqawarn(msg) +def _post_src_install_chost_fix(settings): + """ + It's possible that the ebuild has changed the + CHOST variable, so revert it to the initial + setting. + """ + chost = settings.get('CHOST') + if chost: + write_atomic(os.path.join(settings['PORTAGE_BUILDDIR'], + 'build-info', 'CHOST'), chost + '\n') + def _post_src_install_uid_fix(mysettings): """ Files in $D with user and group bits that match the "portage" @@ -4903,6 +4915,17 @@ def _post_src_install_uid_fix(mysettings): """ inst_uid = int(mysettings["PORTAGE_INST_UID"]) inst_gid = int(mysettings["PORTAGE_INST_GID"]) + + if bsd_chflags: + # Temporarily remove all of the flags in order to avoid EPERM errors. + os.system("mtree -c -p %s -k flags > %s" % \ + (_shell_quote(mysettings["D"]), + _shell_quote(os.path.join(mysettings["T"], "bsdflags.mtree")))) + os.system("chflags -R noschg,nouchg,nosappnd,nouappnd %s" % \ + (_shell_quote(mysettings["D"]),)) + os.system("chflags -R nosunlnk,nouunlnk %s 2>/dev/null" % \ + (_shell_quote(mysettings["D"]),)) + for parent, dirs, files in os.walk(mysettings["D"]): for fname in chain(dirs, files): fpath = os.path.join(parent, fname) @@ -4920,6 +4943,12 @@ def _post_src_install_uid_fix(mysettings): mode=mystat.st_mode, stat_cached=mystat, follow_links=False) + if bsd_chflags: + # Restore all of the flags saved above. + os.system("mtree -e -p %s -U -k flags < %s > /dev/null" % \ + (_shell_quote(mysettings["D"]), + _shell_quote(os.path.join(mysettings["T"], "bsdflags.mtree")))) + def _post_pkg_preinst_cmd(mysettings): """ Post phase logic and tasks that have been factored out of -- 2.26.2