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