beff660427f959c5e2b7aa75dd8c598551f97473
[genkernel.git] / gen_funcs.sh
1 #!/bin/bash
2 # $Id$
3
4 isTrue() {
5         case "$1" in
6                 [Tt][Rr][Uu][Ee])
7                         return 0
8                 ;;
9                 [Tt])
10                         return 0
11                 ;;
12                 [Yy][Ee][Ss])
13                         return 0
14                 ;;
15                 [Yy])
16                         return 0
17                 ;;
18                 1)
19                         return 0
20                 ;;
21         esac
22         return 1
23 }
24
25 setColorVars() { 
26 if isTrue ${USECOLOR}
27 then
28         GOOD=$'\e[32;01m'
29         WARN=$'\e[33;01m'
30         BAD=$'\e[31;01m'
31         NORMAL=$'\e[0m'
32         BOLD=$'\e[0;01m'
33         UNDER=$'\e[4m'
34 else
35         GOOD=''
36         WARN=''
37         BAD=''
38         NORMAL=''
39         BOLD=''
40         UNDER=''
41 fi
42 }
43 setColorVars
44
45 dump_debugcache() {
46         TODEBUGCACHE=0
47         echo "${DEBUGCACHE}" >> ${LOGFILE}
48 }
49
50 # print_info(loglevel, print [, newline [, prefixline [, forcefile ] ] ])
51 print_info() {
52         local NEWLINE=1
53         local FORCEFILE=0
54         local PREFIXLINE=1
55         local SCRPRINT=0
56         local STR=''
57
58         # NOT ENOUGH ARGS
59         if [ "$#" -lt '2' ] ; then return 1; fi
60
61         # IF 3 OR MORE ARGS, CHECK IF WE WANT A NEWLINE AFTER PRINT
62         if [ "$#" -gt '2' ]
63         then
64                 if isTrue "$3"
65                 then
66                         NEWLINE='1';
67                 else
68                         NEWLINE='0';
69                 fi
70         fi
71
72         # IF 4 OR MORE ARGS, CHECK IF WE WANT TO PREFIX WITH A *
73         if [ "$#" -gt '3' ]
74         then
75                 if isTrue "$4"
76                 then
77                         PREFIXLINE='1'
78                 else
79                         PREFIXLINE='0'
80                 fi
81         fi
82
83         # IF 5 OR MORE ARGS, CHECK IF WE WANT TO FORCE OUTPUT TO DEBUG
84         # FILE EVEN IF IT DOESN'T MEET THE MINIMUM DEBUG REQS
85         if [ "$#" -gt '4' ]
86         then
87                 if isTrue "$5"
88                 then
89                         FORCEFILE='1'
90                 else
91                         FORCEFILE='0'
92                 fi
93         fi
94
95         # PRINT TO SCREEN ONLY IF PASSED LOGLEVEL IS HIGHER THAN
96         # OR EQUAL TO SET DEBUG LEVEL
97         if [ "$1" -lt "${LOGLEVEL}" -o "$1" = "${LOGLEVEL}" ]
98         then
99                 SCRPRINT='1'
100         fi
101
102         # RETURN IF NOT OUTPUTTING ANYWHERE
103         if [ "${SCRPRINT}" != '1' -a "${FORCEFILE}" != '1' ]
104         then
105                 return 0
106         fi
107
108         # STRUCTURE DATA TO BE OUTPUT TO SCREEN, AND OUTPUT IT
109         if [ "${SCRPRINT}" = '1' ]
110         then
111                 if [ "${PREFIXLINE}" = '1' ]
112                 then
113                         STR="${GOOD}*${NORMAL} ${2}"
114                 else
115                         STR="${2}"
116                 fi
117
118                 if [ "${NEWLINE}" = '0' ]
119                 then
120                         echo -ne "${STR}"
121                 else
122                         echo "${STR}"
123                 fi
124         fi
125
126         # STRUCTURE DATA TO BE OUTPUT TO FILE, AND OUTPUT IT
127         if [ "${SCRPRINT}" = '1' -o "${FORCEFILE}" = '1' ]
128         then
129                 STRR=${2//${WARN}/}
130                 STRR=${STRR//${BAD}/}
131                 STRR=${STRR//${BOLD}/}
132                 STRR=${STRR//${NORMAL}/}
133
134                 if [ "${PREFIXLINE}" = '1' ]
135                 then
136                         STR="* ${STRR}"
137                 else
138                         STR="${STRR}"
139                 fi
140
141                 if [ "${NEWLINE}" = '0' ]
142                 then
143                         if [ "${TODEBUGCACHE}" = '1' ]; then
144                                 DEBUGCACHE="${DEBUGCACHE}${STR}"
145                         else
146                                 echo -ne "${STR}" >> ${LOGFILE}
147                         fi      
148                 else
149                         if [ "${TODEBUGCACHE}" = '1' ]; then
150                                 DEBUGCACHE="${DEBUGCACHE}${STR}"$'\n'
151                         else
152                                 echo "${STR}" >> ${LOGFILE}
153                         fi
154                 fi
155         fi
156
157         return 0
158 }
159
160 print_error()
161 {
162         GOOD=${BAD} print_info "$@"
163 }
164
165 print_warning()
166 {
167         GOOD=${WARN} print_info "$@"
168 }
169
170 # var_replace(var_name, var_value, string)
171 # $1 = variable name
172 # $2 = variable value
173 # $3 = string
174
175 var_replace()
176 {
177   # Escape '\' and '.' in $2 to make it safe to use
178   # in the later sed expression
179   local SAFE_VAR
180   SAFE_VAR=`echo "${2}" | sed -e 's/\([\/\.]\)/\\\\\\1/g'`
181   
182   echo "${3}" | sed -e "s/%%${1}%%/${SAFE_VAR}/g" -
183 }
184
185 arch_replace() {
186   var_replace "ARCH" "${ARCH}" "${1}"
187 }
188
189 cache_replace() {
190   var_replace "CACHE" "${CACHE_DIR}" "${1}"
191 }
192
193 clear_log() {
194     if [ -f "${LOGFILE}" ]
195     then
196         (echo > "${LOGFILE}") 2>/dev/null || small_die "Genkernel: Could not write to ${LOGFILE}."
197     fi   
198 }
199
200 gen_die() {
201         dump_debugcache
202
203         if [ "$#" -gt '0' ]
204         then
205                 print_error 1 "ERROR: ${1}"
206         fi
207         echo
208         print_info 1 "-- Grepping log... --"
209         echo
210
211         if isTrue ${USECOLOR}
212         then
213                 GREP_COLOR='1' grep -B5 -E --colour=always "([Ww][Aa][Rr][Nn][Ii][Nn][Gg]|[Ee][Rr][Rr][Oo][Rr][ :,!]|[Ff][Aa][Ii][Ll][Ee]?[Dd]?)" ${LOGFILE}
214         else
215                 grep -B5 -E "([Ww][Aa][Rr][Nn][Ii][Nn][Gg]|[Ee][Rr][Rr][Oo][Rr][ :,!]|[Ff][Aa][Ii][Ll][Ee]?[Dd]?)" ${LOGFILE}
216         fi
217         echo
218         print_info 1 "-- End log... --"
219         echo
220         print_info 1 "Please consult ${LOGFILE} for more information and any"
221         print_info 1 "errors that were reported above."
222         echo
223         print_info 1 "Report any genkernel bugs to bugs.gentoo.org and"
224         print_info 1 "assign your bug to genkernel@gentoo.org. Please include"
225         print_info 1 "as much information as you can in your bug report; attaching"
226         print_info 1 "${LOGFILE} so that your issue can be dealt with effectively."
227         print_info 1 ''
228         print_info 1 'Please do *not* report compilation failures as genkernel bugs!'
229         print_info 1 ''
230
231         # Cleanup temp dirs and caches if requested
232         cleanup
233         exit 1
234 }
235
236 isBootRO()
237 {
238         return $(awk '( $2 == "'${BOOTDIR}'" && $4 ~ /(^|,)ro(,|$)/){ I=1; exit }END{print !I }' /proc/mounts);
239 }
240
241 setup_cache_dir()
242 {
243
244 [ ! -d "${CACHE_DIR}" ] && mkdir -p "${CACHE_DIR}"
245
246 if [ "${CLEAR_CACHE_DIR}" == 'yes' ]
247 then
248         print_info 1 "Clearing cache dir contents from ${CACHE_DIR}"
249         while read i
250         do
251                 print_info 1 "   >> removing ${i}"
252                 rm "${i}"
253         done < <(find "${CACHE_DIR}" -maxdepth 1 -type f -name '*.tar.*' -o -name '*.bz2')
254 fi
255
256 }
257
258 clear_tmpdir()
259 {
260 if ! isTrue ${CMD_NOINSTALL}
261 then
262         TMPDIR_CONTENTS=`ls ${TMPDIR}`
263         print_info 1 "Removing tmp dir contents"
264         for i in ${TMPDIR_CONTENTS}
265         do
266                 print_info 1 "   >> removing ${i}"
267                 rm ${TMPDIR}/${i}
268         done
269 fi
270 }       
271
272 #
273 # Function to copy various kernel boot image products to the boot directory,
274 # preserve a generation of old images (just like the manual kernel build's
275 # "make install" does), and maintain the symlinks (if enabled).
276 #
277 # Arguments:
278 #     $1  Symlink name.  Symlink on the boot directory. Path not included.
279 #     $2  Source image.  Fully qualified path name of the source image.
280 #     $3  Dest image.    Name of the destination image in the boot directory,
281 #         no path included.  This script pushd's into ${BOOTDIR} in order to
282 #         create relative symlinks just like the manual kernel build.
283 #
284 # - JRG
285 #
286 copy_image_with_preserve() {
287         local symlinkName=$1
288         local newSrceImage=$2
289         local fullDestName=$3
290
291         local currDestImage
292         local prevDestImage
293         local currDestImageExists=0
294         local prevDestImageExists=0
295
296         print_info 4 "Copying new ${symlinkName} image, " 0
297
298         # Old product might be a different version.  If so, we need to read
299         # the symlink to see what it's name is, if there are symlinks.
300         if [ "${SYMLINK}" = '1' ]
301         then
302                 print_info 4 "automatically managing symlinks and old images." 1 0
303                 if [ -e "${BOOTDIR}/${symlinkName}" ]
304                 then
305                         # JRG: Do I need a special case here for when the standard symlink
306                         # name is, in fact, not a symlink?
307                         currDestImage=`readlink --no-newline ${BOOTDIR}/${symlinkName}`
308                         print_info 5 "  Current ${symlinkName} symlink exists:"
309                         print_info 5 "    ${currDestImage}"
310                 else
311                         currDestImage="${fullDestName}"
312                         print_info 5 "  Current ${symlinkName} symlink did not exist."
313                         print_info 5 "    Defaulted to: ${currDestImage}"
314                 fi
315                 if [ -e "${BOOTDIR}/${currDestImage}" ]
316                 then
317                         currDestImageExists=1
318                         print_info 5 "  Actual image file exists."
319                 fi
320
321                 if [ -e "${BOOTDIR}/${symlinkName}.old" ]
322                 then
323                         # JRG: Do I need a special case here for when the standard symlink
324                         # name is, in fact, not a symlink?
325                         prevDestImage=`readlink --no-newline ${BOOTDIR}/${symlinkName}.old`
326                         print_info 5 "  Old ${symlinkName} symlink exists:"
327                         print_info 5 "    ${prevDestImage}"
328                 else
329                         prevDestImage="${fullDestName}.old"
330                         print_info 5 "  Old ${symlinkName} symlink did not exist."
331                         print_info 5 "    Defaulted to: ${prevDestImage}"
332                 fi
333                 if [ -e "${BOOTDIR}/${prevDestImage}" ]
334                 then
335                         prevDestImageExists=1
336                         print_info 5 "  Actual old image file exists."
337                 fi
338         else
339                 print_info 4 "symlinks not being handled by genkernel." 1 0
340                 currDestImage="${fullDestName}"
341                 prevDestImage="${fullDestName}.old"
342         fi
343
344         # When symlinks are not being managed by genkernel, old symlinks might
345     # still be useful.  Leave 'em alone unless managed.
346         if [ "${SYMLINK}" = '1' ]
347         then
348                 print_info 5 "  Deleting old symlinks, if any."
349                 rm -f "${BOOTDIR}/${symlinkName}"
350                 rm -f "${BOOTDIR}/${symlinkName}.old"
351         fi
352
353         # We only erase the .old image when it is the exact same version as the
354         # current and new images.  Different version .old (and current) images are
355         # left behind.  This is consistent with how "make install" of the manual
356         # kernel build works.
357         if [ "${currDestImage}" == "${fullDestName}" ]
358         then
359                 #
360                 # Case for new and currrent of the same base version.
361                 #
362                 print_info 5 "  Same base version.  May have to delete old image to make room."
363
364                 if [ "${currDestImageExists}" = '1' ]
365                 then
366                         if [ -e "${BOOTDIR}/${currDestImage}.old" ]
367                         then
368                                 print_info 5 "  Deleting old identical version ${symlinkName}."
369                                 rm -f "${BOOTDIR}/${currDestImage}.old"
370                         fi
371                         print_info 5 "  Moving ${BOOTDIR}/${currDestImage}"
372                         print_info 5 "    to ${BOOTDIR}/${currDestImage}.old"
373                         mv "${BOOTDIR}/${currDestImage}" "${BOOTDIR}/${currDestImage}.old" ||
374                             gen_die "Could not rename the old ${symlinkName} image!"
375                         prevDestImage="${currDestImage}.old"
376                         prevDestImageExists=1
377                 fi
378         else
379                 #
380                 # Case for new / current not of the same base version.
381                 #
382                 print_info 5 "  Different base version.  Do not delete old images."
383                 prevDestImage="${currDestImage}"
384                 currDestImage="${fullDestName}"
385         fi
386
387         print_info 5 "  Copying ${symlinkName}: ${newSrceImage}"
388         print_info 5 "    to ${BOOTDIR}/${currDestImage}"
389         cp "${newSrceImage}" "${BOOTDIR}/${currDestImage}" ||
390             gen_die "Could not copy the ${symlinkName} image to ${BOOTDIR}!"
391
392         if [ "${SYMLINK}" = '1' ]
393         then
394                 print_info 5 "  Make new symlink(s) (from ${BOOTDIR}):"
395                 print_info 5 "    ${symlinkName} -> ${currDestImage}"
396                 pushd ${BOOTDIR} >/dev/null
397                 ln -s "${currDestImage}" "${symlinkName}" || 
398                     gen_die "Could not create the ${symlinkName} symlink!"
399                 if [ "${prevDestImageExists}" = '1' ]
400                 then
401                         print_info 5 "    ${symlinkName}.old -> ${prevDestImage}"
402                         ln -s "${prevDestImage}" "${symlinkName}.old" ||
403                             gen_die "Could not create the ${symlinkName}.old symlink!"
404                 fi
405                 popd >/dev/null
406         fi
407 }
408
409 #
410 # Helper function to allow command line arguments to override configuration
411 # file specified values and to apply defaults.
412 #
413 # Arguments:
414 #     $1  Argument type:
415 #           1  Switch type arguments (e.g., --color / --no-color).
416 #           2  Value type arguments (e.g., --debuglevel=5).
417 #     $2  Config file variable name.
418 #     $3  Command line variable name.
419 #     $4  Default.  If both the config file variable and the command line
420 #         option are not present, then the config file variable is set to
421 #         this default value.  Optional.
422 #
423 # The order of priority of these three sources (highest first) is:
424 #     Command line, which overrides
425 #     Config file (/etc/genkernel.conf), which overrides
426 #     Default.
427 #
428 # Arguments $2 and $3 are variable *names*, not *values*.  This function uses
429 # various forms of indirection to access the values.
430 #
431 # For switch type arguments, all forms of "True" are converted to a numeric 1
432 # and all forms of "False" (everything else, really) to a numeric 0.
433 #
434 # - JRG
435 #
436 set_config_with_override() {
437         local VarType=$1
438         local CfgVar=$2
439         local OverrideVar=$3
440         local Default=$4
441         local Result
442
443         #
444         # Syntax check the function arguments.
445         #
446         case "$VarType" in
447                 1|2)
448                         ;;
449                 *)
450                         gen_die "Illegal variable type \"$VarType\" passed to set_config_with_override()."
451                         ;;
452         esac
453
454         if [ -n "${!OverrideVar}" ]
455         then
456                 Result=${!OverrideVar}
457                 if [ -n "${!CfgVar}" ]
458                 then
459                         print_info 5 "  $CfgVar overridden on command line to \"$Result\"."
460                 else
461                         print_info 5 "  $CfgVar set on command line to \"$Result\"."
462                 fi
463         else
464                 if [ -n "${!CfgVar}" ]
465                 then
466                         Result=${!CfgVar}
467                         # we need to set the CMD_* according to configfile...
468                         eval ${OverrideVar}=\"${Result}\"
469                         print_info 5 "  $CfgVar set in config file to \"${Result}\"."
470                 else
471                         if [ -n "$Default" ]
472                         then
473                                 Result=${Default}
474                                 # set OverrideVar to Result, otherwise CMD_* may not be initialized...
475                                 eval ${OverrideVar}=\"${Result}\"
476                                 print_info 5 "  $CfgVar defaulted to \"${Result}\"."
477                         else
478                                 print_info 5 "  $CfgVar not set."
479                         fi
480                 fi
481         fi
482
483         if [ "${VarType}" = "1" ]
484         then
485                 if isTrue "${Result}"
486                 then
487                         Result=1
488                 else
489                         Result=0
490                 fi
491         fi
492
493         eval ${CfgVar}=\"${Result}\"
494 }
495
496 check_distfiles() {
497         for i in $BUSYBOX_SRCTAR $DEVICE_MAPPER_SRCTAR $MULTIPATH_SRCTAR $LVM_SRCTAR $DMRAID_SRCTAR $E2FSPROGS_SRCTAR $ISCSI_SRCTAR $GPG_SRCTAR
498         do
499                 if [ ! -f "${i}" ]
500                 then
501                         small_die "Could not find source tarball ${i}. Please refetch."
502                 fi
503         done
504 }
505
506 find_kernel_binary() {
507         local kernel_binary=$*
508         local curdir=$(pwd)
509
510         cd "${KERNEL_DIR}"
511         for i in ${kernel_binary}
512         do
513                 if [ -e "${i}" ]
514                 then
515                         tmp_kernel_binary=$i
516                         break
517                 fi
518         done
519 #       if [ -z "${tmp_kernel_binary}" ]
520 #       then
521 #               gen_die "Cannot locate kernel binary!"
522 #       fi
523         cd "${curdir}"
524         echo "${tmp_kernel_binary}"
525 }