dyn_install: skip copy if possible
[portage.git] / bin / misc-functions.sh
1 #!/bin/bash
2 # Copyright 1999-2011 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4 #
5 # Miscellaneous shell functions that make use of the ebuild env but don't need
6 # to be included directly in ebuild.sh.
7 #
8 # We're sourcing ebuild.sh here so that we inherit all of it's goodness,
9 # including bashrc trickery.  This approach allows us to do our miscellaneous
10 # shell work withing the same env that ebuild.sh has, but without polluting
11 # ebuild.sh itself with unneeded logic and shell code.
12 #
13 # XXX hack: clear the args so ebuild.sh doesn't see them
14 MISC_FUNCTIONS_ARGS="$@"
15 shift $#
16
17 source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}/ebuild.sh"
18
19 install_symlink_html_docs() {
20         [[ " ${FEATURES} " == *" force-prefix "* ]] || \
21                 case "$EAPI" in 0|1|2) local ED=${D} ;; esac
22         cd "${ED}" || die "cd failed"
23         #symlink the html documentation (if DOC_SYMLINKS_DIR is set in make.conf)
24         if [ -n "${DOC_SYMLINKS_DIR}" ] ; then
25                 local mydocdir docdir
26                 for docdir in "${HTMLDOC_DIR:-does/not/exist}" "${PF}/html" "${PF}/HTML" "${P}/html" "${P}/HTML" ; do
27                         if [ -d "usr/share/doc/${docdir}" ] ; then
28                                 mydocdir="/usr/share/doc/${docdir}"
29                         fi
30                 done
31                 if [ -n "${mydocdir}" ] ; then
32                         local mysympath
33                         if [ -z "${SLOT}" -o "${SLOT}" = "0" ] ; then
34                                 mysympath="${DOC_SYMLINKS_DIR}/${CATEGORY}/${PN}"
35                         else
36                                 mysympath="${DOC_SYMLINKS_DIR}/${CATEGORY}/${PN}-${SLOT}"
37                         fi
38                         einfo "Symlinking ${mysympath} to the HTML documentation"
39                         dodir "${DOC_SYMLINKS_DIR}/${CATEGORY}"
40                         dosym "${mydocdir}" "${mysympath}"
41                 fi
42         fi
43 }
44
45 # replacement for "readlink -f" or "realpath"
46 canonicalize() {
47         local f=$1 b n=10 wd=$(pwd)
48         while (( n-- > 0 )); do
49                 while [[ ${f: -1} = / && ${#f} -gt 1 ]]; do
50                         f=${f%/}
51                 done
52                 b=${f##*/}
53                 cd "${f%"${b}"}" 2>/dev/null || break
54                 if [[ ! -L ${b} ]]; then
55                         f=$(pwd -P)
56                         echo "${f%/}/${b}"
57                         cd "${wd}"
58                         return 0
59                 fi
60                 f=$(readlink "${b}")
61         done
62         cd "${wd}"
63         return 1
64 }
65
66 prepcompress() {
67         local -a include exclude incl_d incl_f
68         local f g i real_f real_d
69         [[ " ${FEATURES} " == *" force-prefix "* ]] || \
70                 case "$EAPI" in 0|1|2) local ED=${D} ;; esac
71
72         # Canonicalize path names and check for their existence.
73         real_d=$(canonicalize "${ED}")
74         for (( i = 0; i < ${#PORTAGE_DOCOMPRESS[@]}; i++ )); do
75                 real_f=$(canonicalize "${ED}${PORTAGE_DOCOMPRESS[i]}")
76                 f=${real_f#"${real_d}"}
77                 if [[ ${real_f} != "${f}" ]] && [[ -d ${real_f} || -f ${real_f} ]]
78                 then
79                         include[${#include[@]}]=${f:-/}
80                 elif [[ ${i} -ge 3 ]]; then
81                         ewarn "prepcompress:" \
82                                 "ignoring nonexistent path '${PORTAGE_DOCOMPRESS[i]}'"
83                 fi
84         done
85         for (( i = 0; i < ${#PORTAGE_DOCOMPRESS_SKIP[@]}; i++ )); do
86                 real_f=$(canonicalize "${ED}${PORTAGE_DOCOMPRESS_SKIP[i]}")
87                 f=${real_f#"${real_d}"}
88                 if [[ ${real_f} != "${f}" ]] && [[ -d ${real_f} || -f ${real_f} ]]
89                 then
90                         exclude[${#exclude[@]}]=${f:-/}
91                 elif [[ ${i} -ge 1 ]]; then
92                         ewarn "prepcompress:" \
93                                 "ignoring nonexistent path '${PORTAGE_DOCOMPRESS_SKIP[i]}'"
94                 fi
95         done
96
97         # Remove redundant entries from lists.
98         # For the include list, remove any entries that are:
99         # a) contained in a directory in the include or exclude lists, or
100         # b) identical with an entry in the exclude list.
101         for (( i = ${#include[@]} - 1; i >= 0; i-- )); do
102                 f=${include[i]}
103                 for g in "${include[@]}"; do
104                         if [[ ${f} == "${g%/}"/* ]]; then
105                                 unset include[i]
106                                 continue 2
107                         fi
108                 done
109                 for g in "${exclude[@]}"; do
110                         if [[ ${f} = "${g}" || ${f} == "${g%/}"/* ]]; then
111                                 unset include[i]
112                                 continue 2
113                         fi
114                 done
115         done
116         # For the exclude list, remove any entries that are:
117         # a) contained in a directory in the exclude list, or
118         # b) _not_ contained in a directory in the include list.
119         for (( i = ${#exclude[@]} - 1; i >= 0; i-- )); do
120                 f=${exclude[i]}
121                 for g in "${exclude[@]}"; do
122                         if [[ ${f} == "${g%/}"/* ]]; then
123                                 unset exclude[i]
124                                 continue 2
125                         fi
126                 done
127                 for g in "${include[@]}"; do
128                         [[ ${f} == "${g%/}"/* ]] && continue 2
129                 done
130                 unset exclude[i]
131         done
132
133         # Split the include list into directories and files
134         for f in "${include[@]}"; do
135                 if [[ -d ${ED}${f} ]]; then
136                         incl_d[${#incl_d[@]}]=${f}
137                 else
138                         incl_f[${#incl_f[@]}]=${f}
139                 fi
140         done
141
142         # Queue up for compression.
143         # ecompress{,dir} doesn't like to be called with empty argument lists.
144         [[ ${#incl_d[@]} -gt 0 ]] && ecompressdir --queue "${incl_d[@]}"
145         [[ ${#incl_f[@]} -gt 0 ]] && ecompress --queue "${incl_f[@]/#/${ED}}"
146         [[ ${#exclude[@]} -gt 0 ]] && ecompressdir --ignore "${exclude[@]}"
147         return 0
148 }
149
150 install_qa_check() {
151         local f i qa_var x
152         [[ " ${FEATURES} " == *" force-prefix "* ]] || \
153                 case "$EAPI" in 0|1|2) local ED=${D} ;; esac
154
155         cd "${ED}" || die "cd failed"
156
157         # Merge QA_FLAGS_IGNORED and QA_DT_HASH into a single array, since
158         # QA_DT_HASH is deprecated.
159         qa_var="QA_FLAGS_IGNORED_${ARCH/-/_}"
160         eval "[[ -n \${!qa_var} ]] && QA_FLAGS_IGNORED=(\"\${${qa_var}[@]}\")"
161         if [[ ${#QA_FLAGS_IGNORED[@]} -eq 1 ]] ; then
162                 local shopts=$-
163                 set -o noglob
164                 QA_FLAGS_IGNORED=(${QA_FLAGS_IGNORED})
165                 set +o noglob
166                 set -${shopts}
167         fi
168
169         qa_var="QA_DT_HASH_${ARCH/-/_}"
170         eval "[[ -n \${!qa_var} ]] && QA_DT_HASH=(\"\${${qa_var}[@]}\")"
171         if [[ ${#QA_DT_HASH[@]} -eq 1 ]] ; then
172                 local shopts=$-
173                 set -o noglob
174                 QA_DT_HASH=(${QA_DT_HASH})
175                 set +o noglob
176                 set -${shopts}
177         fi
178
179         if [[ -n ${QA_DT_HASH} ]] ; then
180                 QA_FLAGS_IGNORED=("${QA_FLAGS_IGNORED[@]}" "${QA_DT_HASH[@]}")
181                 unset QA_DT_HASH
182         fi
183
184         # Merge QA_STRICT_FLAGS_IGNORED and QA_STRICT_DT_HASH, since
185         # QA_STRICT_DT_HASH is deprecated
186         if [ "${QA_STRICT_FLAGS_IGNORED-unset}" = unset ] && \
187                 [ "${QA_STRICT_DT_HASH-unset}" != unset ] ; then
188                 QA_STRICT_FLAGS_IGNORED=1
189                 unset QA_STRICT_DT_HASH
190         fi
191
192         # Check for files built without respecting *FLAGS. Note that
193         # -frecord-gcc-switches must be in all *FLAGS variables, in
194         # order to avoid false positive results here.
195         # NOTE: This check must execute before prepall/prepstrip, since
196         # prepstrip strips the .GCC.command.line sections.
197         if type -P scanelf > /dev/null && ! has binchecks ${RESTRICT} && \
198                 [[ "${CFLAGS}" == *-frecord-gcc-switches* ]] && \
199                 [[ "${CXXFLAGS}" == *-frecord-gcc-switches* ]] && \
200                 [[ "${FFLAGS}" == *-frecord-gcc-switches* ]] && \
201                 [[ "${FCFLAGS}" == *-frecord-gcc-switches* ]] ; then
202                 rm -f "${T}"/scanelf-ignored-CFLAGS.log
203                 for x in $(scanelf -qyRF '%k %p' -k \!.GCC.command.line "${ED}" | \
204                         sed -e "s:\!.GCC.command.line ::") ; do
205                         # Separate out file types that are known to support
206                         # .GCC.command.line sections, using the `file` command
207                         # similar to how prepstrip uses it.
208                         f=$(file "${x}") || continue
209                         [[ -z ${f} ]] && continue
210                         if [[ ${f} == *"SB executable"* ||
211                                 ${f} == *"SB shared object"* ]] ; then
212                                 echo "${x}" >> "${T}"/scanelf-ignored-CFLAGS.log
213                         fi
214                 done
215
216                 if [[ -f "${T}"/scanelf-ignored-CFLAGS.log ]] ; then
217
218                         if [ "${QA_STRICT_FLAGS_IGNORED-unset}" = unset ] ; then
219                                 for x in "${QA_FLAGS_IGNORED[@]}" ; do
220                                         sed -e "s#^${x#/}\$##" -i "${T}"/scanelf-ignored-CFLAGS.log
221                                 done
222                         fi
223                         # Filter anything under /usr/lib/debug/ in order to avoid
224                         # duplicate warnings for splitdebug files.
225                         sed -e "s#^usr/lib/debug/.*##" -e "/^\$/d" -e "s#^#/#" \
226                                 -i "${T}"/scanelf-ignored-CFLAGS.log
227                         f=$(<"${T}"/scanelf-ignored-CFLAGS.log)
228                         if [[ -n ${f} ]] ; then
229                                 vecho -ne '\n'
230                                 eqawarn "${BAD}QA Notice: Files built without respecting CFLAGS have been detected${NORMAL}"
231                                 eqawarn " Please include the following list of files in your report:"
232                                 eqawarn "${f}"
233                                 vecho -ne '\n'
234                                 sleep 1
235                         else
236                                 rm -f "${T}"/scanelf-ignored-CFLAGS.log
237                         fi
238                 fi
239         fi
240
241         export STRIP_MASK
242         prepall
243         has "${EAPI}" 0 1 2 3 || prepcompress
244         ecompressdir --dequeue
245         ecompress --dequeue
246
247         # Prefix specific checks
248         [[ ${ED} != ${D} ]] && install_qa_check_prefix
249
250         f=
251         for x in etc/app-defaults usr/man usr/info usr/X11R6 usr/doc usr/locale ; do
252                 [[ -d ${ED}/$x ]] && f+="  $x\n"
253         done
254
255         if [[ -n $f ]] ; then
256                 eqawarn "QA Notice: This ebuild installs into the following deprecated directories:"
257                 eqawarn
258                 eqawarn "$f"
259         fi
260
261         # Now we look for all world writable files.
262         local unsafe_files=$(find "${ED}" -type f -perm -2 | sed -e "s:^${ED}:- :")
263         if [[ -n ${unsafe_files} ]] ; then
264                 vecho "QA Security Notice: world writable file(s):"
265                 vecho "${unsafe_files}"
266                 vecho "- This may or may not be a security problem, most of the time it is one."
267                 vecho "- Please double check that $PF really needs a world writeable bit and file bugs accordingly."
268                 sleep 1
269         fi
270
271         if type -P scanelf > /dev/null && ! has binchecks ${RESTRICT}; then
272                 local insecure_rpath=0 tmp_quiet=${PORTAGE_QUIET}
273                 local x
274
275                 # display warnings when using stricter because we die afterwards
276                 if has stricter ${FEATURES} ; then
277                         unset PORTAGE_QUIET
278                 fi
279
280                 # Make sure we disallow insecure RUNPATH/RPATHs.
281                 #   1) References to PORTAGE_BUILDDIR are banned because it's a
282                 #      security risk. We don't want to load files from a
283                 #      temporary directory.
284                 #   2) If ROOT != "/", references to ROOT are banned because
285                 #      that directory won't exist on the target system.
286                 #   3) Null paths are banned because the loader will search $PWD when
287                 #      it finds null paths.
288                 local forbidden_dirs="${PORTAGE_BUILDDIR}"
289                 if [[ -n "${ROOT}" && "${ROOT}" != "/" ]]; then
290                         forbidden_dirs+=" ${ROOT}"
291                 fi
292                 local dir l rpath_files=$(scanelf -F '%F:%r' -qBR "${ED}")
293                 f=""
294                 for dir in ${forbidden_dirs}; do
295                         for l in $(echo "${rpath_files}" | grep -E ":${dir}|::|: "); do
296                                 f+="  ${l%%:*}\n"
297                                 if ! has stricter ${FEATURES}; then
298                                         vecho "Auto fixing rpaths for ${l%%:*}"
299                                         TMPDIR="${dir}" scanelf -BXr "${l%%:*}" -o /dev/null
300                                 fi
301                         done
302                 done
303
304                 # Reject set*id binaries with $ORIGIN in RPATH #260331
305                 x=$(
306                         find "${ED}" -type f \( -perm -u+s -o -perm -g+s \) -print0 | \
307                         xargs -0 scanelf -qyRF '%r %p' | grep '$ORIGIN'
308                 )
309
310                 # Print QA notice.
311                 if [[ -n ${f}${x} ]] ; then
312                         vecho -ne '\n'
313                         eqawarn "QA Notice: The following files contain insecure RUNPATHs"
314                         eqawarn " Please file a bug about this at http://bugs.gentoo.org/"
315                         eqawarn " with the maintaining herd of the package."
316                         eqawarn "${f}${f:+${x:+\n}}${x}"
317                         vecho -ne '\n'
318                         if [[ -n ${x} ]] || has stricter ${FEATURES} ; then
319                                 insecure_rpath=1
320                         fi
321                 fi
322
323                 # TEXTRELs are baaaaaaaad
324                 # Allow devs to mark things as ignorable ... e.g. things that are
325                 # binary-only and upstream isn't cooperating (nvidia-glx) ... we
326                 # allow ebuild authors to set QA_TEXTRELS_arch and QA_TEXTRELS ...
327                 # the former overrides the latter ... regexes allowed ! :)
328                 qa_var="QA_TEXTRELS_${ARCH/-/_}"
329                 [[ -n ${!qa_var} ]] && QA_TEXTRELS=${!qa_var}
330                 [[ -n ${QA_STRICT_TEXTRELS} ]] && QA_TEXTRELS=""
331                 export QA_TEXTRELS="${QA_TEXTRELS} lib*/modules/*.ko"
332                 f=$(scanelf -qyRF '%t %p' "${ED}" | grep -v 'usr/lib/debug/')
333                 if [[ -n ${f} ]] ; then
334                         scanelf -qyRAF '%T %p' "${PORTAGE_BUILDDIR}"/ &> "${T}"/scanelf-textrel.log
335                         vecho -ne '\n'
336                         eqawarn "QA Notice: The following files contain runtime text relocations"
337                         eqawarn " Text relocations force the dynamic linker to perform extra"
338                         eqawarn " work at startup, waste system resources, and may pose a security"
339                         eqawarn " risk.  On some architectures, the code may not even function"
340                         eqawarn " properly, if at all."
341                         eqawarn " For more information, see http://hardened.gentoo.org/pic-fix-guide.xml"
342                         eqawarn " Please include the following list of files in your report:"
343                         eqawarn "${f}"
344                         vecho -ne '\n'
345                         die_msg="${die_msg} textrels,"
346                         sleep 1
347                 fi
348
349                 # Also, executable stacks only matter on linux (and just glibc atm ...)
350                 f=""
351                 case ${CTARGET:-${CHOST}} in
352                         *-linux-gnu*)
353                         # Check for files with executable stacks, but only on arches which
354                         # are supported at the moment.  Keep this list in sync with
355                         # http://hardened.gentoo.org/gnu-stack.xml (Arch Status)
356                         case ${CTARGET:-${CHOST}} in
357                                 arm*|i?86*|ia64*|m68k*|s390*|sh*|x86_64*)
358                                         # Allow devs to mark things as ignorable ... e.g. things
359                                         # that are binary-only and upstream isn't cooperating ...
360                                         # we allow ebuild authors to set QA_EXECSTACK_arch and
361                                         # QA_EXECSTACK ... the former overrides the latter ...
362                                         # regexes allowed ! :)
363
364                                         qa_var="QA_EXECSTACK_${ARCH/-/_}"
365                                         [[ -n ${!qa_var} ]] && QA_EXECSTACK=${!qa_var}
366                                         [[ -n ${QA_STRICT_EXECSTACK} ]] && QA_EXECSTACK=""
367                                         qa_var="QA_WX_LOAD_${ARCH/-/_}"
368                                         [[ -n ${!qa_var} ]] && QA_WX_LOAD=${!qa_var}
369                                         [[ -n ${QA_STRICT_WX_LOAD} ]] && QA_WX_LOAD=""
370                                         export QA_EXECSTACK="${QA_EXECSTACK} lib*/modules/*.ko"
371                                         export QA_WX_LOAD="${QA_WX_LOAD} lib*/modules/*.ko"
372                                         f=$(scanelf -qyRAF '%e %p' "${ED}" | grep -v 'usr/lib/debug/')
373                                         ;;
374                         esac
375                         ;;
376                 esac
377                 if [[ -n ${f} ]] ; then
378                         # One more pass to help devs track down the source
379                         scanelf -qyRAF '%e %p' "${PORTAGE_BUILDDIR}"/ &> "${T}"/scanelf-execstack.log
380                         vecho -ne '\n'
381                         eqawarn "QA Notice: The following files contain writable and executable sections"
382                         eqawarn " Files with such sections will not work properly (or at all!) on some"
383                         eqawarn " architectures/operating systems.  A bug should be filed at"
384                         eqawarn " http://bugs.gentoo.org/ to make sure the issue is fixed."
385                         eqawarn " For more information, see http://hardened.gentoo.org/gnu-stack.xml"
386                         eqawarn " Please include the following list of files in your report:"
387                         eqawarn " Note: Bugs should be filed for the respective maintainers"
388                         eqawarn " of the package in question and not hardened@g.o."
389                         eqawarn "${f}"
390                         vecho -ne '\n'
391                         die_msg="${die_msg} execstacks"
392                         sleep 1
393                 fi
394
395                 # Check for files built without respecting LDFLAGS
396                 if [[ "${LDFLAGS}" == *,--hash-style=gnu* ]] && \
397                         ! has binchecks ${RESTRICT} ; then 
398                         f=$(scanelf -qyRF '%k %p' -k .hash "${ED}" | sed -e "s:\.hash ::")
399                         if [[ -n ${f} ]] ; then
400                                 echo "${f}" > "${T}"/scanelf-ignored-LDFLAGS.log
401                                 if [ "${QA_STRICT_FLAGS_IGNORED-unset}" = unset ] ; then
402                                         for x in "${QA_FLAGS_IGNORED[@]}" ; do
403                                                 sed -e "s#^${x#/}\$##" -i "${T}"/scanelf-ignored-LDFLAGS.log
404                                         done
405                                 fi
406                                 # Filter anything under /usr/lib/debug/ in order to avoid
407                                 # duplicate warnings for splitdebug files.
408                                 sed -e "s#^usr/lib/debug/.*##" -e "/^\$/d" -e "s#^#/#" \
409                                         -i "${T}"/scanelf-ignored-LDFLAGS.log
410                                 f=$(<"${T}"/scanelf-ignored-LDFLAGS.log)
411                                 if [[ -n ${f} ]] ; then
412                                         vecho -ne '\n'
413                                         eqawarn "${BAD}QA Notice: Files built without respecting LDFLAGS have been detected${NORMAL}"
414                                         eqawarn " Please include the following list of files in your report:"
415                                         eqawarn "${f}"
416                                         vecho -ne '\n'
417                                         sleep 1
418                                 else
419                                         rm -f "${T}"/scanelf-ignored-LDFLAGS.log
420                                 fi
421                         fi
422                 fi
423
424                 # Save NEEDED information after removing self-contained providers
425                 rm -f "$PORTAGE_BUILDDIR"/build-info/NEEDED{,.ELF.2}
426                 scanelf -qyRF '%a;%p;%S;%r;%n' "${D}" | { while IFS= read -r l; do
427                         arch=${l%%;*}; l=${l#*;}
428                         obj="/${l%%;*}"; l=${l#*;}
429                         soname=${l%%;*}; l=${l#*;}
430                         rpath=${l%%;*}; l=${l#*;}; [ "${rpath}" = "  -  " ] && rpath=""
431                         needed=${l%%;*}; l=${l#*;}
432                         if [ -z "${rpath}" -o -n "${rpath//*ORIGIN*}" ]; then
433                                 # object doesn't contain $ORIGIN in its runpath attribute
434                                 echo "${obj} ${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED
435                                 echo "${arch:3};${obj};${soname};${rpath};${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.ELF.2
436                         else
437                                 dir=${obj%/*}
438                                 # replace $ORIGIN with the dirname of the current object for the lookup
439                                 opath=$(echo :${rpath}: | sed -e "s#.*:\(.*\)\$ORIGIN\(.*\):.*#\1${dir}\2#")
440                                 sneeded=$(echo ${needed} | tr , ' ')
441                                 rneeded=""
442                                 for lib in ${sneeded}; do
443                                         found=0
444                                         for path in ${opath//:/ }; do
445                                                 [ -e "${D}/${path}/${lib}" ] && found=1 && break
446                                         done
447                                         [ "${found}" -eq 0 ] && rneeded="${rneeded},${lib}"
448                                 done
449                                 rneeded=${rneeded:1}
450                                 if [ -n "${rneeded}" ]; then
451                                         echo "${obj} ${rneeded}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED
452                                         echo "${arch:3};${obj};${soname};${rpath};${rneeded}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.ELF.2
453                                 fi
454                         fi
455                 done }
456
457                 [ -n "${QA_SONAME_NO_SYMLINK}" ] && \
458                         echo "${QA_SONAME_NO_SYMLINK}" > \
459                         "${PORTAGE_BUILDDIR}"/build-info/QA_SONAME_NO_SYMLINK
460
461                 if [[ ${insecure_rpath} -eq 1 ]] ; then
462                         die "Aborting due to serious QA concerns with RUNPATH/RPATH"
463                 elif [[ -n ${die_msg} ]] && has stricter ${FEATURES} ; then
464                         die "Aborting due to QA concerns: ${die_msg}"
465                 fi
466
467                 # Check for shared libraries lacking SONAMEs
468                 qa_var="QA_SONAME_${ARCH/-/_}"
469                 eval "[[ -n \${!qa_var} ]] && QA_SONAME=(\"\${${qa_var}[@]}\")"
470                 f=$(scanelf -ByF '%S %p' "${ED}"{,usr/}lib*/lib*.so* | gawk '$2 == "" { print }' | sed -e "s:^[[:space:]]${ED}:/:")
471                 if [[ -n ${f} ]] ; then
472                         echo "${f}" > "${T}"/scanelf-missing-SONAME.log
473                         if [[ "${QA_STRICT_SONAME-unset}" == unset ]] ; then
474                                 if [[ ${#QA_SONAME[@]} -gt 1 ]] ; then
475                                         for x in "${QA_SONAME[@]}" ; do
476                                                 sed -e "s#^/${x#/}\$##" -i "${T}"/scanelf-missing-SONAME.log
477                                         done
478                                 else
479                                         local shopts=$-
480                                         set -o noglob
481                                         for x in ${QA_SONAME} ; do
482                                                 sed -e "s#^/${x#/}\$##" -i "${T}"/scanelf-missing-SONAME.log
483                                         done
484                                         set +o noglob
485                                         set -${shopts}
486                                 fi
487                         fi
488                         sed -e "/^\$/d" -i "${T}"/scanelf-missing-SONAME.log
489                         f=$(<"${T}"/scanelf-missing-SONAME.log)
490                         if [[ -n ${f} ]] ; then
491                                 vecho -ne '\n'
492                                 eqawarn "QA Notice: The following shared libraries lack a SONAME"
493                                 eqawarn "${f}"
494                                 vecho -ne '\n'
495                                 sleep 1
496                         else
497                                 rm -f "${T}"/scanelf-missing-SONAME.log
498                         fi
499                 fi
500
501                 # Check for shared libraries lacking NEEDED entries
502                 qa_var="QA_DT_NEEDED_${ARCH/-/_}"
503                 eval "[[ -n \${!qa_var} ]] && QA_DT_NEEDED=(\"\${${qa_var}[@]}\")"
504                 f=$(scanelf -ByF '%n %p' "${ED}"{,usr/}lib*/lib*.so* | gawk '$2 == "" { print }' | sed -e "s:^[[:space:]]${ED}:/:")
505                 if [[ -n ${f} ]] ; then
506                         echo "${f}" > "${T}"/scanelf-missing-NEEDED.log
507                         if [[ "${QA_STRICT_DT_NEEDED-unset}" == unset ]] ; then
508                                 if [[ ${#QA_DT_NEEDED[@]} -gt 1 ]] ; then
509                                         for x in "${QA_DT_NEEDED[@]}" ; do
510                                                 sed -e "s#^/${x#/}\$##" -i "${T}"/scanelf-missing-NEEDED.log
511                                         done
512                                 else
513                                         local shopts=$-
514                                         set -o noglob
515                                         for x in ${QA_DT_NEEDED} ; do
516                                                 sed -e "s#^/${x#/}\$##" -i "${T}"/scanelf-missing-NEEDED.log
517                                         done
518                                         set +o noglob
519                                         set -${shopts}
520                                 fi
521                         fi
522                         sed -e "/^\$/d" -i "${T}"/scanelf-missing-NEEDED.log
523                         f=$(<"${T}"/scanelf-missing-NEEDED.log)
524                         if [[ -n ${f} ]] ; then
525                                 vecho -ne '\n'
526                                 eqawarn "QA Notice: The following shared libraries lack NEEDED entries"
527                                 eqawarn "${f}"
528                                 vecho -ne '\n'
529                                 sleep 1
530                         else
531                                 rm -f "${T}"/scanelf-missing-NEEDED.log
532                         fi
533                 fi
534
535                 PORTAGE_QUIET=${tmp_quiet}
536         fi
537
538         local unsafe_files=$(find "${ED}" -type f '(' -perm -2002 -o -perm -4002 ')' | sed -e "s:^${ED}:/:")
539         if [[ -n ${unsafe_files} ]] ; then
540                 eqawarn "QA Notice: Unsafe files detected (set*id and world writable)"
541                 eqawarn "${unsafe_files}"
542                 die "Unsafe files found in \${D}.  Portage will not install them."
543         fi
544
545         if [[ -d ${D}/${D} ]] ; then
546                 declare -i INSTALLTOD=0
547                 for i in $(find "${D}/${D}/"); do
548                         eqawarn "QA Notice: /${i##${D}/${D}} installed in \${D}/\${D}"
549                         ((INSTALLTOD++))
550                 done
551                 die "Aborting due to QA concerns: ${INSTALLTOD} files installed in ${D}/${D}"
552                 unset INSTALLTOD
553         fi
554
555         # Sanity check syntax errors in init.d scripts
556         local d
557         for d in /etc/conf.d /etc/init.d ; do
558                 [[ -d ${ED}/${d} ]] || continue
559                 for i in "${ED}"/${d}/* ; do
560                         [[ -L ${i} ]] && continue
561                         # if empty conf.d/init.d dir exists (baselayout), then i will be "/etc/conf.d/*" and not exist
562                         [[ ! -e ${i} ]] && continue
563                         bash -n "${i}" || die "The init.d file has syntax errors: ${i}"
564                 done
565         done
566
567         # this should help to ensure that all (most?) shared libraries are executable
568         # and that all libtool scripts / static libraries are not executable
569         local j
570         for i in "${ED}"opt/*/lib{,32,64} \
571                  "${ED}"lib{,32,64}       \
572                  "${ED}"usr/lib{,32,64}   \
573                  "${ED}"usr/X11R6/lib{,32,64} ; do
574                 [[ ! -d ${i} ]] && continue
575
576                 for j in "${i}"/*.so.* "${i}"/*.so ; do
577                         [[ ! -e ${j} ]] && continue
578                         [[ -L ${j} ]] && continue
579                         [[ -x ${j} ]] && continue
580                         vecho "making executable: ${j#${ED}}"
581                         chmod +x "${j}"
582                 done
583
584                 for j in "${i}"/*.a "${i}"/*.la ; do
585                         [[ ! -e ${j} ]] && continue
586                         [[ -L ${j} ]] && continue
587                         [[ ! -x ${j} ]] && continue
588                         vecho "removing executable bit: ${j#${ED}}"
589                         chmod -x "${j}"
590                 done
591
592                 for j in "${i}"/*.{a,dll,dylib,sl,so}.* "${i}"/*.{a,dll,dylib,sl,so} ; do
593                         [[ ! -e ${j} ]] && continue
594                         [[ ! -L ${j} ]] && continue
595                         linkdest=$(readlink "${j}")
596                         if [[ ${linkdest} == /* ]] ; then
597                                 vecho -ne '\n'
598                                 eqawarn "QA Notice: Found an absolute symlink in a library directory:"
599                                 eqawarn "           ${j#${D}} -> ${linkdest}"
600                                 eqawarn "           It should be a relative symlink if in the same directory"
601                                 eqawarn "           or a linker script if it crosses the /usr boundary."
602                         fi
603                 done
604         done
605
606         # When installing static libraries into /usr/lib and shared libraries into 
607         # /lib, we have to make sure we have a linker script in /usr/lib along side 
608         # the static library, or gcc will utilize the static lib when linking :(.
609         # http://bugs.gentoo.org/4411
610         abort="no"
611         local a s
612         for a in "${ED}"usr/lib*/*.a ; do
613                 s=${a%.a}.so
614                 if [[ ! -e ${s} ]] ; then
615                         s=${s%usr/*}${s##*/usr/}
616                         if [[ -e ${s} ]] ; then
617                                 vecho -ne '\n'
618                                 eqawarn "QA Notice: Missing gen_usr_ldscript for ${s##*/}"
619                                 abort="yes"
620                         fi
621                 fi
622         done
623         [[ ${abort} == "yes" ]] && die "add those ldscripts"
624
625         # Make sure people don't store libtool files or static libs in /lib
626         f=$(ls "${ED}"lib*/*.{a,la} 2>/dev/null)
627         if [[ -n ${f} ]] ; then
628                 vecho -ne '\n'
629                 eqawarn "QA Notice: Excessive files found in the / partition"
630                 eqawarn "${f}"
631                 vecho -ne '\n'
632                 die "static archives (*.a) and libtool library files (*.la) do not belong in /"
633         fi
634
635         # Verify that the libtool files don't contain bogus $D entries.
636         local abort=no gentoo_bug=no always_overflow=no
637         for a in "${ED}"usr/lib*/*.la ; do
638                 s=${a##*/}
639                 if grep -qs "${ED}" "${a}" ; then
640                         vecho -ne '\n'
641                         eqawarn "QA Notice: ${s} appears to contain PORTAGE_TMPDIR paths"
642                         abort="yes"
643                 fi
644         done
645         [[ ${abort} == "yes" ]] && die "soiled libtool library files found"
646
647         # Evaluate misc gcc warnings
648         if [[ -n ${PORTAGE_LOG_FILE} && -r ${PORTAGE_LOG_FILE} ]] ; then
649                 # In debug mode, this variable definition and corresponding grep calls
650                 # will produce false positives if they're shown in the trace.
651                 local reset_debug=0
652                 if [[ ${-/x/} != $- ]] ; then
653                         set +x
654                         reset_debug=1
655                 fi
656                 local m msgs=(
657                         ": warning: dereferencing type-punned pointer will break strict-aliasing rules"
658                         ": warning: dereferencing pointer .* does break strict-aliasing rules"
659                         ": warning: implicit declaration of function"
660                         ": warning: incompatible implicit declaration of built-in function"
661                         ": warning: is used uninitialized in this function" # we'll ignore "may" and "might"
662                         ": warning: comparisons like X<=Y<=Z do not have their mathematical meaning"
663                         ": warning: null argument where non-null required"
664                         ": warning: array subscript is below array bounds"
665                         ": warning: array subscript is above array bounds"
666                         ": warning: attempt to free a non-heap object"
667                         ": warning: .* called with .*bigger.* than .* destination buffer"
668                         ": warning: call to .* will always overflow destination buffer"
669                         ": warning: assuming pointer wraparound does not occur when comparing"
670                         ": warning: hex escape sequence out of range"
671                         ": warning: [^ ]*-hand operand of comma .*has no effect"
672                         ": warning: converting to non-pointer type .* from NULL"
673                         ": warning: NULL used in arithmetic"
674                         ": warning: passing NULL to non-pointer argument"
675                         ": warning: the address of [^ ]* will always evaluate as"
676                         ": warning: the address of [^ ]* will never be NULL"
677                         ": warning: too few arguments for format"
678                         ": warning: reference to local variable .* returned"
679                         ": warning: returning reference to temporary"
680                         ": warning: function returns address of local variable"
681                         # this may be valid code :/
682                         #": warning: multi-character character constant"
683                         # need to check these two ...
684                         #": warning: assuming signed overflow does not occur when"
685                         #": warning: comparison with string literal results in unspecified behav"
686                         # yacc/lex likes to trigger this one
687                         #": warning: extra tokens at end of .* directive"
688                         # only gcc itself triggers this ?
689                         #": warning: .*noreturn.* function does return"
690                         # these throw false positives when 0 is used instead of NULL
691                         #": warning: missing sentinel in function call"
692                         #": warning: not enough variable arguments to fit a sentinel"
693                 )
694                 abort="no"
695                 i=0
696                 local grep_cmd=grep
697                 [[ $PORTAGE_LOG_FILE = *.gz ]] && grep_cmd=zgrep
698                 while [[ -n ${msgs[${i}]} ]] ; do
699                         m=${msgs[$((i++))]}
700                         # force C locale to work around slow unicode locales #160234
701                         f=$(LC_ALL=C $grep_cmd "${m}" "${PORTAGE_LOG_FILE}")
702                         if [[ -n ${f} ]] ; then
703                                 abort="yes"
704                                 # for now, don't make this fatal (see bug #337031)
705                                 #case "$m" in
706                                 #       ": warning: call to .* will always overflow destination buffer") always_overflow=yes ;;
707                                 #esac
708                                 if [[ $always_overflow = yes ]] ; then
709                                         eerror
710                                         eerror "QA Notice: Package triggers severe warnings which indicate that it"
711                                         eerror "           may exhibit random runtime failures."
712                                         eerror
713                                         eerror "${f}"
714                                         eerror
715                                         eerror " Please file a bug about this at http://bugs.gentoo.org/"
716                                         eerror " with the maintaining herd of the package."
717                                         eerror
718                                 else
719                                         vecho -ne '\n'
720                                         eqawarn "QA Notice: Package triggers severe warnings which indicate that it"
721                                         eqawarn "           may exhibit random runtime failures."
722                                         eqawarn "${f}"
723                                         vecho -ne '\n'
724                                 fi
725                         fi
726                 done
727                 local cat_cmd=cat
728                 [[ $PORTAGE_LOG_FILE = *.gz ]] && cat_cmd=zcat
729                 [[ $reset_debug = 1 ]] && set -x
730                 f=$($cat_cmd "${PORTAGE_LOG_FILE}" | \
731                         "${PORTAGE_PYTHON:-/usr/bin/python}" "$PORTAGE_BIN_PATH"/check-implicit-pointer-usage.py || die "check-implicit-pointer-usage.py failed")
732                 if [[ -n ${f} ]] ; then
733
734                         # In the future this will be a forced "die". In preparation,
735                         # increase the log level from "qa" to "eerror" so that people
736                         # are aware this is a problem that must be fixed asap.
737
738                         # just warn on 32bit hosts but bail on 64bit hosts
739                         case ${CHOST} in
740                                 alpha*|hppa64*|ia64*|powerpc64*|mips64*|sparc64*|sparcv9*|x86_64*) gentoo_bug=yes ;;
741                         esac
742
743                         abort=yes
744
745                         if [[ $gentoo_bug = yes ]] ; then
746                                 eerror
747                                 eerror "QA Notice: Package triggers severe warnings which indicate that it"
748                                 eerror "           will almost certainly crash on 64bit architectures."
749                                 eerror
750                                 eerror "${f}"
751                                 eerror
752                                 eerror " Please file a bug about this at http://bugs.gentoo.org/"
753                                 eerror " with the maintaining herd of the package."
754                                 eerror
755                         else
756                                 vecho -ne '\n'
757                                 eqawarn "QA Notice: Package triggers severe warnings which indicate that it"
758                                 eqawarn "           will almost certainly crash on 64bit architectures."
759                                 eqawarn "${f}"
760                                 vecho -ne '\n'
761                         fi
762
763                 fi
764                 if [[ ${abort} == "yes" ]] ; then
765                         if [[ $gentoo_bug = yes || $always_overflow = yes ]] ; then
766                                 die "install aborted due to" \
767                                         "severe warnings shown above"
768                         else
769                                 echo "Please do not file a Gentoo bug and instead" \
770                                 "report the above QA issues directly to the upstream" \
771                                 "developers of this software." | fmt -w 70 | \
772                                 while read -r line ; do eqawarn "${line}" ; done
773                                 eqawarn "Homepage: ${HOMEPAGE}"
774                                 has stricter ${FEATURES} && die "install aborted due to" \
775                                         "severe warnings shown above"
776                         fi
777                 fi
778         fi
779
780         # Portage regenerates this on the installed system.
781         rm -f "${ED}"/usr/share/info/dir{,.gz,.bz2}
782
783         if has multilib-strict ${FEATURES} && \
784            [[ -x /usr/bin/file && -x /usr/bin/find ]] && \
785            [[ -n ${MULTILIB_STRICT_DIRS} && -n ${MULTILIB_STRICT_DENY} ]]
786         then
787                 local abort=no dir file firstrun=yes
788                 MULTILIB_STRICT_EXEMPT=$(echo ${MULTILIB_STRICT_EXEMPT} | sed -e 's:\([(|)]\):\\\1:g')
789                 for dir in ${MULTILIB_STRICT_DIRS} ; do
790                         [[ -d ${ED}/${dir} ]] || continue
791                         for file in $(find ${ED}/${dir} -type f | grep -v "^${ED}/${dir}/${MULTILIB_STRICT_EXEMPT}"); do
792                                 if file ${file} | egrep -q "${MULTILIB_STRICT_DENY}" ; then
793                                         if [[ ${firstrun} == yes ]] ; then
794                                                 echo "Files matching a file type that is not allowed:"
795                                                 firstrun=no
796                                         fi
797                                         abort=yes
798                                         echo "   ${file#${ED}//}"
799                                 fi
800                         done
801                 done
802                 [[ ${abort} == yes ]] && die "multilib-strict check failed!"
803         fi
804
805         # ensure packages don't install systemd units automagically
806         if ! has systemd ${INHERITED} && \
807                 [[ -d "${ED}"/lib/systemd/system ]]
808         then
809                 eqawarn "QA Notice: package installs systemd unit files (/lib/systemd/system)"
810                 eqawarn "           but does not inherit systemd.eclass."
811                 has stricter ${FEATURES} \
812                         && die "install aborted due to missing inherit of systemd.eclass"
813         fi
814 }
815
816 install_qa_check_prefix() {
817         if [[ -d ${ED}/${D} ]] ; then
818                 find "${ED}/${D}" | \
819                 while read i ; do
820                         eqawarn "QA Notice: /${i##${ED}/${D}} installed in \${ED}/\${D}"
821                 done
822                 die "Aborting due to QA concerns: files installed in ${ED}/${D}"
823         fi
824
825         if [[ -d ${ED}/${EPREFIX} ]] ; then
826                 find "${ED}/${EPREFIX}/" | \
827                 while read i ; do
828                         eqawarn "QA Notice: ${i#${D}} double prefix"
829                 done
830                 die "Aborting due to QA concerns: double prefix files installed"
831         fi
832
833         if [[ -d ${D} ]] ; then
834                 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;} }')
835                 if [[ -n ${INSTALLTOD} ]] ; then
836                         eqawarn "QA Notice: the following files are outside of the prefix:"
837                         eqawarn "${INSTALLTOD}"
838                         die "Aborting due to QA concerns: there are files installed outside the prefix"
839                 fi
840         fi
841
842         # all further checks rely on ${ED} existing
843         [[ -d ${ED} ]] || return
844
845         # this does not really belong here, but it's closely tied to
846         # the code below; many runscripts generate positives here, and we
847         # know they don't work (bug #196294) so as long as that one
848         # remains an issue, simply remove them as they won't work
849         # anyway, avoid etc/init.d/functions.sh from being thrown away
850         if [[ ( -d "${ED}"/etc/conf.d || -d "${ED}"/etc/init.d ) && ! -f "${ED}"/etc/init.d/functions.sh ]] ; then
851                 ewarn "removed /etc/init.d and /etc/conf.d directories until bug #196294 has been resolved"
852                 rm -Rf "${ED}"/etc/{conf,init}.d
853         fi
854
855         # check shebangs, bug #282539
856         rm -f "${T}"/non-prefix-shebangs-errs
857         local WHITELIST=" /usr/bin/env "
858         # this is hell expensive, but how else?
859         find "${ED}" -executable \! -type d -print0 \
860                         | xargs -0 grep -H -n -m1 "^#!" \
861                         | while read f ;
862         do
863                 local fn=${f%%:*}
864                 local pos=${f#*:} ; pos=${pos%:*}
865                 local line=${f##*:}
866                 # shebang always appears on the first line ;)
867                 [[ ${pos} != 1 ]] && continue
868                 local oldIFS=${IFS}
869                 IFS=$'\r'$'\n'$'\t'" "
870                 line=( ${line#"#!"} )
871                 IFS=${oldIFS}
872                 [[ ${WHITELIST} == *" ${line[0]} "* ]] && continue
873                 local fp=${fn#${D}} ; fp=/${fp%/*}
874                 # line[0] can be an absolutised path, bug #342929
875                 local eprefix=$(canonicalize ${EPREFIX})
876                 local rf=${fn}
877                 # in case we deal with a symlink, make sure we don't replace it
878                 # with a real file (sed -i does that)
879                 if [[ -L ${fn} ]] ; then
880                         rf=$(readlink ${fn})
881                         [[ ${rf} != /* ]] && rf=${fn%/*}/${rf}
882                         # ignore symlinks pointing to outside prefix
883                         # as seen in sys-devel/native-cctools
884                         [[ $(canonicalize "/${rf#${D}}") != ${eprefix}/* ]] && continue
885                 fi
886                 # does the shebang start with ${EPREFIX}, and does it exist?
887                 if [[ ${line[0]} == ${EPREFIX}/* || ${line[0]} == ${eprefix}/* ]] ; then
888                         if [[ ! -e ${ROOT%/}${line[0]} && ! -e ${D%/}${line[0]} ]] ; then
889                                 # hmm, refers explicitly to $EPREFIX, but doesn't exist,
890                                 # if it's in PATH that's wrong in any case
891                                 if [[ ":${PATH}:" == *":${fp}:"* ]] ; then
892                                         echo "${fn#${D}}:${line[0]} (explicit EPREFIX but target not found)" \
893                                                 >> "${T}"/non-prefix-shebangs-errs
894                                 else
895                                         eqawarn "${fn#${D}} has explicit EPREFIX in shebang but target not found (${line[0]})"
896                                 fi
897                         fi
898                         continue
899                 fi
900                 # unprefixed shebang, is the script directly in $PATH?
901                 if [[ ":${PATH}:" == *":${fp}:"* ]] ; then
902                         if [[ -e ${EROOT}${line[0]} || -e ${ED}${line[0]} ]] ; then
903                                 # is it unprefixed, but we can just fix it because a
904                                 # prefixed variant exists
905                                 eqawarn "prefixing shebang of ${fn#${D}}"
906                                 # statement is made idempotent on purpose, because
907                                 # symlinks may point to the same target, and hence the
908                                 # same real file may be sedded multiple times since we
909                                 # read the shebangs in one go upfront for performance
910                                 # reasons
911                                 sed -i -e '1s:^#! \?'"${line[0]}"':#!'"${EPREFIX}"${line[0]}':' "${rf}"
912                                 continue
913                         else
914                                 # this is definitely wrong: script in $PATH and invalid shebang
915                                 echo "${fn#${D}}:${line[0]} (script ${fn##*/} installed in PATH but interpreter ${line[0]} not found)" \
916                                         >> "${T}"/non-prefix-shebangs-errs
917                         fi
918                 else
919                         # unprefixed/invalid shebang, but outside $PATH, this may be
920                         # intended (e.g. config.guess) so remain silent by default
921                         has stricter ${FEATURES} && \
922                                 eqawarn "invalid shebang in ${fn#${D}}: ${line[0]}"
923                 fi
924         done
925         if [[ -e "${T}"/non-prefix-shebangs-errs ]] ; then
926                 eqawarn "QA Notice: the following files use invalid (possible non-prefixed) shebangs:"
927                 while read line ; do
928                         eqawarn "  ${line}"
929                 done < "${T}"/non-prefix-shebangs-errs
930                 rm -f "${T}"/non-prefix-shebangs-errs
931                 die "Aborting due to QA concerns: invalid shebangs found"
932         fi
933 }
934
935 install_mask() {
936         local root="$1"
937         shift
938         local install_mask="$*"
939
940         # we don't want globbing for initial expansion, but afterwards, we do
941         local shopts=$-
942         set -o noglob
943         local no_inst
944         for no_inst in ${install_mask}; do
945                 set +o noglob
946                 quiet_mode || einfo "Removing ${no_inst}"
947                 # normal stuff
948                 rm -Rf "${root}"/${no_inst} >&/dev/null
949
950                 # we also need to handle globs (*.a, *.h, etc)
951                 find "${root}" \( -path "${no_inst}" -or -name "${no_inst}" \) \
952                         -exec rm -fR {} \; >/dev/null 2>&1
953         done
954         # set everything back the way we found it
955         set +o noglob
956         set -${shopts}
957 }
958
959 preinst_mask() {
960         if [ -z "${D}" ]; then
961                  eerror "${FUNCNAME}: D is unset"
962                  return 1
963         fi
964
965         [[ " ${FEATURES} " == *" force-prefix "* ]] || \
966                 case "$EAPI" in 0|1|2) local ED=${D} ;; esac
967
968         # Make sure $PWD is not ${D} so that we don't leave gmon.out files
969         # in there in case any tools were built with -pg in CFLAGS.
970         cd "${T}"
971
972         # remove man pages, info pages, docs if requested
973         local f
974         for f in man info doc; do
975                 if has no${f} $FEATURES; then
976                         INSTALL_MASK="${INSTALL_MASK} /usr/share/${f}"
977                 fi
978         done
979
980         install_mask "${ED}" "${INSTALL_MASK}"
981
982         # remove share dir if unnessesary
983         if has nodoc $FEATURES || has noman $FEATURES || has noinfo $FEATURES; then
984                 rmdir "${ED}usr/share" &> /dev/null
985         fi
986 }
987
988 preinst_sfperms() {
989         if [ -z "${D}" ]; then
990                  eerror "${FUNCNAME}: D is unset"
991                  return 1
992         fi
993
994         [[ " ${FEATURES} " == *" force-prefix "* ]] || \
995                 case "$EAPI" in 0|1|2) local ED=${D} ;; esac
996
997         # Smart FileSystem Permissions
998         if has sfperms $FEATURES; then
999                 local i
1000                 find "${ED}" -type f -perm -4000 -print0 | \
1001                 while read -r -d $'\0' i ; do
1002                         if [ -n "$(find "$i" -perm -2000)" ] ; then
1003                                 ebegin ">>> SetUID and SetGID: [chmod o-r] /${i#${ED}}"
1004                                 chmod o-r "$i"
1005                                 eend $?
1006                         else
1007                                 ebegin ">>> SetUID: [chmod go-r] /${i#${ED}}"
1008                                 chmod go-r "$i"
1009                                 eend $?
1010                         fi
1011                 done
1012                 find "${ED}" -type f -perm -2000 -print0 | \
1013                 while read -r -d $'\0' i ; do
1014                         if [ -n "$(find "$i" -perm -4000)" ] ; then
1015                                 # This case is already handled
1016                                 # by the SetUID check above.
1017                                 true
1018                         else
1019                                 ebegin ">>> SetGID: [chmod o-r] /${i#${ED}}"
1020                                 chmod o-r "$i"
1021                                 eend $?
1022                         fi
1023                 done
1024         fi
1025 }
1026
1027 preinst_suid_scan() {
1028         if [ -z "${D}" ]; then
1029                  eerror "${FUNCNAME}: D is unset"
1030                  return 1
1031         fi
1032
1033         [[ " ${FEATURES} " == *" force-prefix "* ]] || \
1034                 case "$EAPI" in 0|1|2) local ED=${D} ;; esac
1035
1036         # total suid control.
1037         if has suidctl $FEATURES; then
1038                 local i sfconf x
1039                 sfconf=${PORTAGE_CONFIGROOT}etc/portage/suidctl.conf
1040                 # sandbox prevents us from writing directly
1041                 # to files outside of the sandbox, but this
1042                 # can easly be bypassed using the addwrite() function
1043                 addwrite "${sfconf}"
1044                 vecho ">>> Performing suid scan in ${ED}"
1045                 for i in $(find "${ED}" -type f \( -perm -4000 -o -perm -2000 \) ); do
1046                         if [ -s "${sfconf}" ]; then
1047                                 install_path=/${i#${ED}}
1048                                 if grep -q "^${install_path}\$" "${sfconf}" ; then
1049                                         vecho "- ${install_path} is an approved suid file"
1050                                 else
1051                                         vecho ">>> Removing sbit on non registered ${install_path}"
1052                                         for x in 5 4 3 2 1 0; do sleep 0.25 ; done
1053                                         ls_ret=$(ls -ldh "${i}")
1054                                         chmod ugo-s "${i}"
1055                                         grep "^#${install_path}$" "${sfconf}" > /dev/null || {
1056                                                 vecho ">>> Appending commented out entry to ${sfconf} for ${PF}"
1057                                                 echo "## ${ls_ret%${ED}*}${install_path}" >> "${sfconf}"
1058                                                 echo "#${install_path}" >> "${sfconf}"
1059                                                 # no delwrite() eh?
1060                                                 # delwrite ${sconf}
1061                                         }
1062                                 fi
1063                         else
1064                                 vecho "suidctl feature set but you are lacking a ${sfconf}"
1065                         fi
1066                 done
1067         fi
1068 }
1069
1070 preinst_selinux_labels() {
1071         if [ -z "${D}" ]; then
1072                  eerror "${FUNCNAME}: D is unset"
1073                  return 1
1074         fi
1075         if has selinux ${FEATURES}; then
1076                 # SELinux file labeling (needs to always be last in dyn_preinst)
1077                 # only attempt to label if setfiles is executable
1078                 # and 'context' is available on selinuxfs.
1079                 if [ -f /selinux/context -a -x /usr/sbin/setfiles -a -x /usr/sbin/selinuxconfig ]; then
1080                         vecho ">>> Setting SELinux security labels"
1081                         (
1082                                 eval "$(/usr/sbin/selinuxconfig)" || \
1083                                         die "Failed to determine SELinux policy paths.";
1084         
1085                                 addwrite /selinux/context;
1086         
1087                                 /usr/sbin/setfiles "${file_contexts_path}" -r "${D}" "${D}"
1088                         ) || die "Failed to set SELinux security labels."
1089                 else
1090                         # nonfatal, since merging can happen outside a SE kernel
1091                         # like during a recovery situation
1092                         vecho "!!! Unable to set SELinux security labels"
1093                 fi
1094         fi
1095 }
1096
1097 dyn_package() {
1098         local PROOT
1099
1100         [[ " ${FEATURES} " == *" force-prefix "* ]] || \
1101                 case "$EAPI" in 0|1|2) local EPREFIX= ED=${D} ;; esac
1102
1103         # Make sure $PWD is not ${D} so that we don't leave gmon.out files
1104         # in there in case any tools were built with -pg in CFLAGS.
1105
1106         cd "${T}"
1107
1108         if [[ -n ${PKG_INSTALL_MASK} ]] ; then
1109                 PROOT=${T}/packaging/
1110                 # make a temporary copy of ${D} so that any modifications we do that
1111                 # are binpkg specific, do not influence the actual installed image.
1112                 rm -rf "${PROOT}" || die "failed removing stale package tree"
1113                 cp -pPR $(cp --help | grep -qs -e-l && echo -l) \
1114                         "${D}" "${PROOT}" \
1115                         || die "failed creating packaging tree"
1116
1117                 install_mask "${PROOT%/}${EPREFIX}/" "${PKG_INSTALL_MASK}"
1118         else
1119                 PROOT=${D}
1120         fi
1121
1122         local tar_options=""
1123         [[ $PORTAGE_VERBOSE = 1 ]] && tar_options+=" -v"
1124         # Sandbox is disabled in case the user wants to use a symlink
1125         # for $PKGDIR and/or $PKGDIR/All.
1126         export SANDBOX_ON="0"
1127         [ -z "${PORTAGE_BINPKG_TMPFILE}" ] && \
1128                 die "PORTAGE_BINPKG_TMPFILE is unset"
1129         mkdir -p "${PORTAGE_BINPKG_TMPFILE%/*}" || die "mkdir failed"
1130         tar $tar_options -cf - $PORTAGE_BINPKG_TAR_OPTS -C "${PROOT}" . | \
1131                 $PORTAGE_BZIP2_COMMAND -c > "$PORTAGE_BINPKG_TMPFILE"
1132         assert "failed to pack binary package: '$PORTAGE_BINPKG_TMPFILE'"
1133         PYTHONPATH=${PORTAGE_PYM_PATH}${PYTHONPATH:+:}${PYTHONPATH} \
1134                 "${PORTAGE_PYTHON:-/usr/bin/python}" "$PORTAGE_BIN_PATH"/xpak-helper.py recompose \
1135                 "$PORTAGE_BINPKG_TMPFILE" "$PORTAGE_BUILDDIR/build-info"
1136         if [ $? -ne 0 ]; then
1137                 rm -f "${PORTAGE_BINPKG_TMPFILE}"
1138                 die "Failed to append metadata to the tbz2 file"
1139         fi
1140         local md5_hash=""
1141         if type md5sum &>/dev/null ; then
1142                 md5_hash=$(md5sum "${PORTAGE_BINPKG_TMPFILE}")
1143                 md5_hash=${md5_hash%% *}
1144         elif type md5 &>/dev/null ; then
1145                 md5_hash=$(md5 "${PORTAGE_BINPKG_TMPFILE}")
1146                 md5_hash=${md5_hash##* }
1147         fi
1148         [ -n "${md5_hash}" ] && \
1149                 echo ${md5_hash} > "${PORTAGE_BUILDDIR}"/build-info/BINPKGMD5
1150         vecho ">>> Done."
1151
1152         # cleanup our temp tree
1153         [[ -n ${PKG_INSTALL_MASK} ]] && rm -rf "${PROOT}"
1154         cd "${PORTAGE_BUILDDIR}"
1155         >> "$PORTAGE_BUILDDIR/.packaged" || \
1156                 die "Failed to create $PORTAGE_BUILDDIR/.packaged"
1157 }
1158
1159 dyn_spec() {
1160         local sources_dir=/usr/src/rpm/SOURCES
1161         mkdir -p "${sources_dir}"
1162         declare -a tar_args=("${EBUILD}")
1163         [[ -d ${FILESDIR} ]] && tar_args=("${EBUILD}" "${FILESDIR}")
1164         tar czf "${sources_dir}/${PF}.tar.gz" \
1165                 "${tar_args[@]}" || \
1166                 die "Failed to create base rpm tarball."
1167
1168         cat <<__END1__ > ${PF}.spec
1169 Summary: ${DESCRIPTION}
1170 Name: ${PN}
1171 Version: ${PV}
1172 Release: ${PR}
1173 Copyright: GPL
1174 Group: portage/${CATEGORY}
1175 Source: ${PF}.tar.gz
1176 Buildroot: ${D}
1177 %description
1178 ${DESCRIPTION}
1179
1180 ${HOMEPAGE}
1181
1182 %prep
1183 %setup -c
1184
1185 %build
1186
1187 %install
1188
1189 %clean
1190
1191 %files
1192 /
1193 __END1__
1194
1195 }
1196
1197 dyn_rpm() {
1198
1199         [[ " ${FEATURES} " == *" force-prefix "* ]] || \
1200                 case "$EAPI" in 0|1|2) local EPREFIX= ;; esac
1201
1202         cd "${T}" || die "cd failed"
1203         local machine_name=$(uname -m)
1204         local dest_dir=${EPREFIX}/usr/src/rpm/RPMS/${machine_name}
1205         addwrite ${EPREFIX}/usr/src/rpm
1206         addwrite "${RPMDIR}"
1207         dyn_spec
1208         rpmbuild -bb --clean --rmsource "${PF}.spec" || die "Failed to integrate rpm spec file"
1209         install -D "${dest_dir}/${PN}-${PV}-${PR}.${machine_name}.rpm" \
1210                 "${RPMDIR}/${CATEGORY}/${PN}-${PV}-${PR}.rpm" || \
1211                 die "Failed to move rpm"
1212 }
1213
1214 die_hooks() {
1215         [[ -f $PORTAGE_BUILDDIR/.die_hooks ]] && return
1216         local x
1217         for x in $EBUILD_DEATH_HOOKS ; do
1218                 $x >&2
1219         done
1220         > "$PORTAGE_BUILDDIR/.die_hooks"
1221 }
1222
1223 success_hooks() {
1224         local x
1225         for x in $EBUILD_SUCCESS_HOOKS ; do
1226                 $x
1227         done
1228 }
1229
1230 install_hooks() {
1231         local hooks_dir="${PORTAGE_CONFIGROOT}etc/portage/hooks/install"
1232         local fp
1233         local ret=0
1234         shopt -s nullglob
1235         for fp in "${hooks_dir}"/*; do
1236                 if [ -x "$fp" ]; then
1237                         "$fp"
1238                         ret=$(( $ret | $? ))
1239                 fi
1240         done
1241         shopt -u nullglob
1242         return $ret
1243 }
1244
1245 if [ -n "${MISC_FUNCTIONS_ARGS}" ]; then
1246         source_all_bashrcs
1247         [ "$PORTAGE_DEBUG" == "1" ] && set -x
1248         for x in ${MISC_FUNCTIONS_ARGS}; do
1249                 ${x}
1250         done
1251         unset x
1252         [[ -n $PORTAGE_EBUILD_EXIT_FILE ]] && > "$PORTAGE_EBUILD_EXIT_FILE"
1253         if [[ -n $PORTAGE_IPC_DAEMON ]] ; then
1254                 [[ ! -s $SANDBOX_LOG ]]
1255                 "$PORTAGE_BIN_PATH"/ebuild-ipc exit $?
1256         fi
1257 fi
1258
1259 :