1# Copyright (C) 2009 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# 15 16# A collection of shell function definitions used by various build scripts 17# in the Android NDK (Native Development Kit) 18# 19 20# Get current script name into PROGNAME 21PROGNAME=`basename $0` 22 23# Find the Android NDK root, assuming we are invoked from a script 24# within its directory structure. 25# 26# $1: Variable name that will receive the path 27# $2: Path of invoking script 28find_ndk_root () 29{ 30 # Try to auto-detect the NDK root by walking up the directory 31 # path to the current script. 32 local PROGDIR="`dirname \"$2\"`" 33 while [ -n "1" ] ; do 34 if [ -d "$PROGDIR/build/core" ] ; then 35 break 36 fi 37 if [ -z "$PROGDIR" -o "$PROGDIR" = '/' ] ; then 38 return 1 39 fi 40 PROGDIR="`cd \"$PROGDIR/..\" && pwd`" 41 done 42 eval $1="$PROGDIR" 43} 44 45# Put location of Android NDK into ANDROID_NDK_ROOT and 46# perform a tiny amount of sanity check 47# 48if [ -z "$ANDROID_NDK_ROOT" ] ; then 49 find_ndk_root ANDROID_NDK_ROOT "$0" 50 if [ $? != 0 ]; then 51 echo "Please define ANDROID_NDK_ROOT to point to the root of your" 52 echo "Android NDK installation." 53 exit 1 54 fi 55fi 56 57echo "$ANDROID_NDK_ROOT" | grep -q -e " " 58if [ $? = 0 ] ; then 59 echo "ERROR: The Android NDK installation path contains a space !" 60 echo "Please install to a different location." 61 exit 1 62fi 63 64if [ ! -d $ANDROID_NDK_ROOT ] ; then 65 echo "ERROR: Your ANDROID_NDK_ROOT variable does not point to a directory." 66 exit 1 67fi 68 69if [ ! -f $ANDROID_NDK_ROOT/build/core/ndk-common.sh ] ; then 70 echo "ERROR: Your ANDROID_NDK_ROOT variable does not point to a valid directory." 71 exit 1 72fi 73 74## Logging support 75## 76VERBOSE=${VERBOSE-yes} 77VERBOSE2=${VERBOSE2-no} 78 79 80# If NDK_LOGFILE is defined in the environment, use this as the log file 81TMPLOG= 82if [ -n "$NDK_LOGFILE" ] ; then 83 mkdir -p `dirname "$NDK_LOGFILE"` && touch "$NDK_LOGFILE" 84 TMPLOG="$NDK_LOGFILE" 85fi 86 87# Setup a log file where all log() and log2() output will be sent 88# 89# $1: log file path (optional) 90# 91setup_default_log_file () 92{ 93 if [ -n "$NDK_LOGFILE" ] ; then 94 return 95 fi 96 if [ -n "$1" ] ; then 97 NDK_LOGFILE="$1" 98 else 99 NDK_LOGFILE=/tmp/ndk-log-$$.txt 100 fi 101 export NDK_LOGFILE 102 TMPLOG="$NDK_LOGFILE" 103 rm -rf "$TMPLOG" && mkdir -p `dirname "$TMPLOG"` && touch "$TMPLOG" 104 echo "To follow build in another terminal, please use: tail -F $TMPLOG" 105} 106 107dump () 108{ 109 if [ -n "$TMPLOG" ] ; then 110 echo "$@" >> $TMPLOG 111 fi 112 echo "$@" 113} 114 115dump_n () 116{ 117 if [ -n "$TMPLOG" ] ; then 118 printf %s "$@" >> $TMPLOG 119 fi 120 printf %s "$@" 121} 122 123log () 124{ 125 if [ "$VERBOSE" = "yes" ] ; then 126 echo "$@" 127 else 128 if [ -n "$TMPLOG" ] ; then 129 echo "$@" >> $TMPLOG 130 fi 131 fi 132} 133 134log_n () 135{ 136 if [ "$VERBOSE" = "yes" ] ; then 137 printf %s "$@" 138 else 139 if [ -n "$TMPLOG" ] ; then 140 printf %s "$@" >> $TMPLOG 141 fi 142 fi 143} 144 145log2 () 146{ 147 if [ "$VERBOSE2" = "yes" ] ; then 148 echo "$@" 149 else 150 if [ -n "$TMPLOG" ] ; then 151 echo "$@" >> $TMPLOG 152 fi 153 fi 154} 155 156run () 157{ 158 if [ "$VERBOSE" = "yes" ] ; then 159 echo "## COMMAND: $@" 160 "$@" 2>&1 161 else 162 if [ -n "$TMPLOG" ] ; then 163 echo "## COMMAND: $@" >> $TMPLOG 164 "$@" >>$TMPLOG 2>&1 165 else 166 "$@" > /dev/null 2>&1 167 fi 168 fi 169} 170 171run2 () 172{ 173 if [ "$VERBOSE2" = "yes" ] ; then 174 echo "## COMMAND: $@" 175 "$@" 2>&1 176 elif [ "$VERBOSE" = "yes" ]; then 177 echo "## COMMAND: $@" 178 if [ -n "$TMPLOG" ]; then 179 echo "## COMMAND: $@" >> $TMPLOG 180 "$@" >>$TMPLOG 2>&1 181 else 182 "$@" > /dev/null 2>&1 183 fi 184 else 185 if [ -n "$TMPLOG" ]; then 186 "$@" >>$TMPLOG 2>&1 187 else 188 "$@" > /dev/null 2>&1 189 fi 190 fi 191} 192 193panic () 194{ 195 dump "ERROR: $@" 196 exit 1 197} 198 199fail_panic () 200{ 201 if [ $? != 0 ] ; then 202 dump "ERROR: $@" 203 exit 1 204 fi 205} 206 207 208## Utilities 209## 210 211# Return the value of a given named variable 212# $1: variable name 213# 214# example: 215# FOO=BAR 216# BAR=ZOO 217# echo `var_value $FOO` 218# will print 'ZOO' 219# 220var_value () 221{ 222 # find a better way to do that ? 223 eval echo "$`echo $1`" 224} 225 226# convert to uppercase 227# assumes tr is installed on the platform ? 228# 229to_uppercase () 230{ 231 echo $1 | tr "[:lower:]" "[:upper:]" 232} 233 234## First, we need to detect the HOST CPU, because proper HOST_ARCH detection 235## requires platform-specific tricks. 236## 237HOST_EXE="" 238HOST_OS=`uname -s` 239case "$HOST_OS" in 240 Darwin) 241 HOST_OS=darwin 242 ;; 243 Linux) 244 # note that building 32-bit binaries on x86_64 is handled later 245 HOST_OS=linux 246 ;; 247 FreeBsd) # note: this is not tested 248 HOST_OS=freebsd 249 ;; 250 CYGWIN*|*_NT-*) 251 HOST_OS=windows 252 HOST_EXE=.exe 253 if [ "x$OSTYPE" = xcygwin ] ; then 254 HOST_OS=cygwin 255 fi 256 ;; 257esac 258 259log2 "HOST_OS=$HOST_OS" 260log2 "HOST_EXE=$HOST_EXE" 261 262## Now find the host architecture. This must correspond to the bitness of 263## the binaries we're going to run with this NDK. Certain platforms allow 264## you to use a 64-bit kernel with a 32-bit userland, and unfortunately 265## commands like 'uname -m' only report the kernel bitness. 266## 267HOST_ARCH=`uname -m` 268case "$HOST_ARCH" in 269 i?86) HOST_ARCH=x86 270 ;; 271 amd64) HOST_ARCH=x86_64 272 ;; 273 powerpc) HOST_ARCH=ppc 274 ;; 275esac 276 277case "$HOST_OS-$HOST_ARCH" in 278 linux-x86_64|darwin-x86_64) 279 ## On Linux or Darwin, a 64-bit kernel doesn't mean that the user-land 280 ## is always 32-bit, so use "file" to determine the bitness of the shell 281 ## that invoked us. The -L option is used to de-reference symlinks. 282 ## 283 ## Note that on Darwin, a single executable can contain both x86 and 284 ## x86_64 machine code, so just look for x86_64 (darwin) or x86-64 (Linux) 285 ## in the output. 286 ## 287 file -L "$SHELL" | grep -q "x86[_-]64" 288 if [ $? != 0 ]; then 289 # $SHELL is not a 64-bit executable, so assume our userland is too. 290 log2 "Detected 32-bit userland on 64-bit kernel system!" 291 HOST_ARCH=x86 292 fi 293 ;; 294esac 295 296log2 "HOST_ARCH=$HOST_ARCH" 297 298# at this point, the supported values for HOST_ARCH are: 299# x86 300# x86_64 301# ppc 302# 303# other values may be possible but haven't been tested 304# 305# at this point, the value of HOST_OS should be one of the following: 306# linux 307# darwin 308# windows (MSys) 309# cygwin 310# 311# Note that cygwin is treated as a special case because it behaves very differently 312# for a few things. Other values may be possible but have not been tested 313# 314 315# define HOST_TAG as a unique tag used to identify both the host OS and CPU 316# supported values are: 317# 318# linux-x86 319# linux-x86_64 320# darwin-x86 321# darwin-x86_64 322# darwin-ppc 323# windows 324# windows-x86_64 325# 326# other values are possible but were not tested. 327# 328compute_host_tag () 329{ 330 HOST_TAG=${HOST_OS}-${HOST_ARCH} 331 # Special case for windows-x86 => windows 332 case $HOST_TAG in 333 windows-x86|cygwin-x86) 334 HOST_TAG="windows" 335 ;; 336 esac 337 log2 "HOST_TAG=$HOST_TAG" 338} 339 340compute_host_tag 341 342# Compute the number of host CPU cores an HOST_NUM_CPUS 343# 344case "$HOST_OS" in 345 linux) 346 HOST_NUM_CPUS=`cat /proc/cpuinfo | grep processor | wc -l` 347 ;; 348 darwin|freebsd) 349 HOST_NUM_CPUS=`sysctl -n hw.ncpu` 350 ;; 351 windows|cygwin) 352 HOST_NUM_CPUS=$NUMBER_OF_PROCESSORS 353 ;; 354 *) # let's play safe here 355 HOST_NUM_CPUS=1 356esac 357 358log2 "HOST_NUM_CPUS=$HOST_NUM_CPUS" 359 360# If BUILD_NUM_CPUS is not already defined in your environment, 361# define it as the double of HOST_NUM_CPUS. This is used to 362# run Make commands in parralles, as in 'make -j$BUILD_NUM_CPUS' 363# 364if [ -z "$BUILD_NUM_CPUS" ] ; then 365 BUILD_NUM_CPUS=`expr $HOST_NUM_CPUS \* 2` 366fi 367 368log2 "BUILD_NUM_CPUS=$BUILD_NUM_CPUS" 369 370 371## HOST TOOLCHAIN SUPPORT 372## 373 374# force the generation of 32-bit binaries on 64-bit systems 375# 376FORCE_32BIT=no 377force_32bit_binaries () 378{ 379 if [ "$HOST_ARCH" = x86_64 ] ; then 380 log2 "Forcing generation of 32-bit host binaries on $HOST_ARCH" 381 FORCE_32BIT=yes 382 HOST_ARCH=x86 383 log2 "HOST_ARCH=$HOST_ARCH" 384 compute_host_tag 385 fi 386} 387 388# On Windows, cygwin binaries will be generated by default, but 389# you can force mingw ones that do not link to cygwin.dll if you 390# call this function. 391# 392disable_cygwin () 393{ 394 if [ $HOST_OS = cygwin ] ; then 395 log2 "Disabling cygwin binaries generation" 396 CFLAGS="$CFLAGS -mno-cygwin" 397 LDFLAGS="$LDFLAGS -mno-cygwin" 398 HOST_OS=windows 399 compute_host_tag 400 fi 401} 402 403# Various probes are going to need to run a small C program 404mkdir -p /tmp/ndk-$USER/tmp/tests 405 406TMPC=/tmp/ndk-$USER/tmp/tests/test-$$.c 407TMPO=/tmp/ndk-$USER/tmp/tests/test-$$.o 408TMPE=/tmp/ndk-$USER/tmp/tests/test-$$$EXE 409TMPL=/tmp/ndk-$USER/tmp/tests/test-$$.log 410 411# cleanup temporary files 412clean_temp () 413{ 414 rm -f $TMPC $TMPO $TMPL $TMPE 415} 416 417# cleanup temp files then exit with an error 418clean_exit () 419{ 420 clean_temp 421 exit 1 422} 423 424# this function will setup the compiler and linker and check that they work as advertised 425# note that you should call 'force_32bit_binaries' before this one if you want it to 426# generate 32-bit binaries on 64-bit systems (that support it). 427# 428setup_toolchain () 429{ 430 if [ -z "$CC" ] ; then 431 CC=gcc 432 fi 433 if [ -z "$CXX" ] ; then 434 CXX=g++ 435 fi 436 if [ -z "$CXXFLAGS" ] ; then 437 CXXFLAGS="$CFLAGS" 438 fi 439 if [ -z "$LD" ] ; then 440 LD="$CC" 441 fi 442 443 log2 "Using '$CC' as the C compiler" 444 445 # check that we can compile a trivial C program with this compiler 446 mkdir -p $(dirname "$TMPC") 447 cat > $TMPC <<EOF 448int main(void) {} 449EOF 450 451 if [ "$FORCE_32BIT" = yes ] ; then 452 CC="$CC -m32" 453 CXX="$CXX -m32" 454 LD="$LD -m32" 455 compile 456 if [ $? != 0 ] ; then 457 # sometimes, we need to also tell the assembler to generate 32-bit binaries 458 # this is highly dependent on your GCC installation (and no, we can't set 459 # this flag all the time) 460 CFLAGS="$CFLAGS -Wa,--32" 461 compile 462 fi 463 fi 464 465 compile 466 if [ $? != 0 ] ; then 467 echo "your C compiler doesn't seem to work:" 468 cat $TMPL 469 clean_exit 470 fi 471 log "CC : compiler check ok ($CC)" 472 473 # check that we can link the trivial program into an executable 474 link 475 if [ $? != 0 ] ; then 476 OLD_LD="$LD" 477 LD="$CC" 478 compile 479 link 480 if [ $? != 0 ] ; then 481 LD="$OLD_LD" 482 echo "your linker doesn't seem to work:" 483 cat $TMPL 484 clean_exit 485 fi 486 fi 487 log2 "Using '$LD' as the linker" 488 log "LD : linker check ok ($LD)" 489 490 # check the C++ compiler 491 log2 "Using '$CXX' as the C++ compiler" 492 493 cat > $TMPC <<EOF 494#include <iostream> 495using namespace std; 496int main() 497{ 498 cout << "Hello World!" << endl; 499 return 0; 500} 501EOF 502 503 compile_cpp 504 if [ $? != 0 ] ; then 505 echo "your C++ compiler doesn't seem to work" 506 cat $TMPL 507 clean_exit 508 fi 509 510 log "CXX : C++ compiler check ok ($CXX)" 511 512 # XXX: TODO perform AR checks 513 AR=ar 514 ARFLAGS= 515} 516 517# try to compile the current source file in $TMPC into an object 518# stores the error log into $TMPL 519# 520compile () 521{ 522 log2 "Object : $CC -o $TMPO -c $CFLAGS $TMPC" 523 $CC -o $TMPO -c $CFLAGS $TMPC 2> $TMPL 524} 525 526compile_cpp () 527{ 528 log2 "Object : $CXX -o $TMPO -c $CXXFLAGS $TMPC" 529 $CXX -o $TMPO -c $CXXFLAGS $TMPC 2> $TMPL 530} 531 532# try to link the recently built file into an executable. error log in $TMPL 533# 534link() 535{ 536 log2 "Link : $LD -o $TMPE $TMPO $LDFLAGS" 537 $LD -o $TMPE $TMPO $LDFLAGS 2> $TMPL 538} 539 540# run a command 541# 542execute() 543{ 544 log2 "Running: $*" 545 $* 546} 547 548# perform a simple compile / link / run of the source file in $TMPC 549compile_exec_run() 550{ 551 log2 "RunExec : $CC -o $TMPE $CFLAGS $TMPC" 552 compile 553 if [ $? != 0 ] ; then 554 echo "Failure to compile test program" 555 cat $TMPC 556 cat $TMPL 557 clean_exit 558 fi 559 link 560 if [ $? != 0 ] ; then 561 echo "Failure to link test program" 562 cat $TMPC 563 echo "------" 564 cat $TMPL 565 clean_exit 566 fi 567 $TMPE 568} 569 570pattern_match () 571{ 572 echo "$2" | grep -q -E -e "$1" 573} 574 575# Let's check that we have a working md5sum here 576check_md5sum () 577{ 578 A_MD5=`echo "A" | md5sum | cut -d' ' -f1` 579 if [ "$A_MD5" != "bf072e9119077b4e76437a93986787ef" ] ; then 580 echo "Please install md5sum on this machine" 581 exit 2 582 fi 583} 584 585# Find if a given shell program is available. 586# We need to take care of the fact that the 'which <foo>' command 587# may return either an empty string (Linux) or something like 588# "no <foo> in ..." (Darwin). Also, we need to redirect stderr 589# to /dev/null for Cygwin 590# 591# $1: variable name 592# $2: program name 593# 594# Result: set $1 to the full path of the corresponding command 595# or to the empty/undefined string if not available 596# 597find_program () 598{ 599 local PROG RET 600 PROG=`which $2 2>/dev/null` 601 RET=$? 602 if [ $RET != 0 ]; then 603 PROG= 604 fi 605 eval $1=\"$PROG\" 606 return $RET 607} 608 609prepare_download () 610{ 611 find_program CMD_WGET wget 612 find_program CMD_CURL curl 613 find_program CMD_SCRP scp 614} 615 616# Download a file with either 'curl', 'wget' or 'scp' 617# 618# $1: source URL (e.g. http://foo.com, ssh://blah, /some/path) 619# $2: target file 620download_file () 621{ 622 # Is this HTTP, HTTPS or FTP ? 623 if pattern_match "^(http|https|ftp):.*" "$1"; then 624 if [ -n "$CMD_WGET" ] ; then 625 run $CMD_WGET -O $2 $1 626 elif [ -n "$CMD_CURL" ] ; then 627 run $CMD_CURL -o $2 $1 628 else 629 echo "Please install wget or curl on this machine" 630 exit 1 631 fi 632 return 633 fi 634 635 # Is this SSH ? 636 # Accept both ssh://<path> or <machine>:<path> 637 # 638 if pattern_match "^(ssh|[^:]+):.*" "$1"; then 639 if [ -n "$CMD_SCP" ] ; then 640 scp_src=`echo $1 | sed -e s%ssh://%%g` 641 run $CMD_SCP $scp_src $2 642 else 643 echo "Please install scp on this machine" 644 exit 1 645 fi 646 return 647 fi 648 649 # Is this a file copy ? 650 # Accept both file://<path> or /<path> 651 # 652 if pattern_match "^(file://|/).*" "$1"; then 653 cp_src=`echo $1 | sed -e s%^file://%%g` 654 run cp -f $cp_src $2 655 return 656 fi 657} 658 659 660# Unpack a given archive 661# 662# $1: archive file path 663# $2: optional target directory (current one if omitted) 664# 665unpack_archive () 666{ 667 local ARCHIVE="$1" 668 local DIR=${2-.} 669 local RESULT TARFLAGS ZIPFLAGS 670 mkdir -p "$DIR" 671 if [ "$VERBOSE2" = "yes" ] ; then 672 TARFLAGS="vxpf" 673 ZIPFLAGS="" 674 else 675 TARFLAGS="xpf" 676 ZIPFLAGS="q" 677 fi 678 case "$ARCHIVE" in 679 *.zip) 680 (cd $DIR && run unzip $ZIPFLAGS "$ARCHIVE") 681 ;; 682 *.tar) 683 run tar $TARFLAGS "$ARCHIVE" -C $DIR 684 ;; 685 *.tar.gz) 686 run tar z$TARFLAGS "$ARCHIVE" -C $DIR 687 ;; 688 *.tar.bz2) 689 run tar j$TARFLAGS "$ARCHIVE" -C $DIR 690 ;; 691 *) 692 panic "Cannot unpack archive with unknown extension: $ARCHIVE" 693 ;; 694 esac 695} 696 697# Pack a given archive 698# 699# $1: archive file path (including extension) 700# $2: source directory for archive content 701# $3+: list of files (including patterns), all if empty 702pack_archive () 703{ 704 local ARCHIVE="$1" 705 local SRCDIR="$2" 706 local SRCFILES 707 local TARFLAGS ZIPFLAGS 708 shift; shift; 709 if [ -z "$1" ] ; then 710 SRCFILES="*" 711 else 712 SRCFILES="$@" 713 fi 714 if [ "`basename $ARCHIVE`" = "$ARCHIVE" ] ; then 715 ARCHIVE="`pwd`/$ARCHIVE" 716 fi 717 mkdir -p `dirname $ARCHIVE` 718 if [ "$VERBOSE2" = "yes" ] ; then 719 TARFLAGS="vcf" 720 ZIPFLAGS="-9r" 721 else 722 TARFLAGS="cf" 723 ZIPFLAGS="-9qr" 724 fi 725 case "$ARCHIVE" in 726 *.zip) 727 (cd $SRCDIR && run zip $ZIPFLAGS "$ARCHIVE" $SRCFILES) 728 ;; 729 *.tar) 730 (cd $SRCDIR && run tar $TARFLAGS "$ARCHIVE" $SRCFILES) 731 ;; 732 *.tar.gz) 733 (cd $SRCDIR && run tar z$TARFLAGS "$ARCHIVE" $SRCFILES) 734 ;; 735 *.tar.bz2) 736 (cd $SRCDIR && run tar j$TARFLAGS "$ARCHIVE" $SRCFILES) 737 ;; 738 *) 739 panic "Unsupported archive format: $ARCHIVE" 740 ;; 741 esac 742} 743 744# Copy a directory, create target location if needed 745# 746# $1: source directory 747# $2: target directory location 748# 749copy_directory () 750{ 751 local SRCDIR="$1" 752 local DSTDIR="$2" 753 if [ ! -d "$SRCDIR" ] ; then 754 panic "Can't copy from non-directory: $SRCDIR" 755 fi 756 log "Copying directory: " 757 log " from $SRCDIR" 758 log " to $DSTDIR" 759 mkdir -p "$DSTDIR" && (cd "$SRCDIR" && 2>/dev/null tar cf - *) | (tar xf - -C "$DSTDIR") 760 fail_panic "Cannot copy to directory: $DSTDIR" 761} 762 763# This is the same than copy_directory(), but symlinks will be replaced 764# by the file they actually point to instead. 765copy_directory_nolinks () 766{ 767 local SRCDIR="$1" 768 local DSTDIR="$2" 769 if [ ! -d "$SRCDIR" ] ; then 770 panic "Can't copy from non-directory: $SRCDIR" 771 fi 772 log "Copying directory (without symlinks): " 773 log " from $SRCDIR" 774 log " to $DSTDIR" 775 mkdir -p "$DSTDIR" && (cd "$SRCDIR" && tar chf - *) | (tar xf - -C "$DSTDIR") 776 fail_panic "Cannot copy to directory: $DSTDIR" 777} 778 779# Copy certain files from one directory to another one 780# $1: source directory 781# $2: target directory 782# $3+: file list (including patterns) 783copy_file_list () 784{ 785 local SRCDIR="$1" 786 local DSTDIR="$2" 787 shift; shift; 788 if [ ! -d "$SRCDIR" ] ; then 789 panic "Cant' copy from non-directory: $SRCDIR" 790 fi 791 log "Copying file: $@" 792 log " from $SRCDIR" 793 log " to $DSTDIR" 794 mkdir -p "$DSTDIR" && (cd "$SRCDIR" && tar cf - "$@") | (tar xf - -C "$DSTDIR") 795 fail_panic "Cannot copy files to directory: $DSTDIR" 796} 797 798# Rotate a log file 799# If the given log file exist, add a -1 to the end of the file. 800# If older log files exist, rename them to -<n+1> 801# $1: log file 802# $2: maximum version to retain [optional] 803rotate_log () 804{ 805 # Default Maximum versions to retain 806 local MAXVER="5" 807 local LOGFILE="$1" 808 shift; 809 if [ ! -z "$1" ] ; then 810 local tmpmax="$1" 811 shift; 812 tmpmax=`expr $tmpmax + 0` 813 if [ $tmpmax -lt 1 ] ; then 814 panic "Invalid maximum log file versions '$tmpmax' invalid; defaulting to $MAXVER" 815 else 816 MAXVER=$tmpmax; 817 fi 818 fi 819 820 # Do Nothing if the log file does not exist 821 if [ ! -f "${LOGFILE}" ] ; then 822 return 823 fi 824 825 # Rename existing older versions 826 ver=$MAXVER 827 while [ $ver -ge 1 ] 828 do 829 local prev=$(( $ver - 1 )) 830 local old="-$prev" 831 832 # Instead of old version 0; use the original filename 833 if [ $ver -eq 1 ] ; then 834 old="" 835 fi 836 837 if [ -f "${LOGFILE}${old}" ] ; then 838 mv -f "${LOGFILE}${old}" "${LOGFILE}-${ver}" 839 fi 840 841 ver=$prev 842 done 843} 844