Bash程序  |  279行  |  9.33 KB

#!/bin/bash
#
# Copyright (C) 2010 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

#
# This script imports new versions of Bouncy Castle
# (http://bouncycastle.org) into the Android source tree.  To run, (1)
# fetch the appropriate tarballs (bcprov and bcpkix) from the Bouncy
# Castle repository, (2) check the checksum, and then (3) run:
#   ./import_bouncycastle.sh import bcprov-jdk*-*.tar.gz
#
# IMPORTANT: See README.android for additional details.

# turn on exit on error as well as a warning when it happens
set -e
trap  "echo WARNING: Exiting on non-zero subprocess exit code" ERR;

function die() {
  declare -r message=$1

  echo $message
  exit 1
}

function usage() {
  declare -r message=$1

  if [ ! "$message" = "" ]; then
    echo $message
  fi
  echo "Usage:"
  echo "  ./import_bouncycastle.sh import </path/to/bcprov-jdk*-*.tar.gz>"
  echo "  ./import_bouncycastle.sh regenerate <patch/*.patch>"
  echo "  ./import_bouncycastle.sh generate <patch/*.patch> </path/to/bcprov-jdk*-*.tar.gz>"
  exit 1
}

function main() {
  if [ ! -d patches ]; then
    die "Bouncy Castle patch directory patches/ not found"
  fi

  if [ ! -f bouncycastle.version ]; then
    die "bouncycastle.version not found"
  fi

  source bouncycastle.version
  if [ "$BOUNCYCASTLE_JDK" == "" -o "$BOUNCYCASTLE_VERSION" == "" ]; then
    die "Invalid bouncycastle.version; see README.android for more information"
  fi

  BOUNCYCASTLE_BCPROV_DIR=bcprov-jdk$BOUNCYCASTLE_JDK-$BOUNCYCASTLE_VERSION
  BOUNCYCASTLE_BCPROV_DIR_ORIG=$BOUNCYCASTLE_BCPROV_DIR.orig

  BOUNCYCASTLE_BCPKIX_DIR=bcpkix-jdk$BOUNCYCASTLE_JDK-$BOUNCYCASTLE_VERSION
  BOUNCYCASTLE_BCPKIX_DIR_ORIG=$BOUNCYCASTLE_BCPKIX_DIR.orig

  if [ ! -f bouncycastle.config ]; then
    die "bouncycastle.config not found"
  fi

  source bouncycastle.config
  if [ "$UNNEEDED_BCPROV_SOURCES" == "" -o "$NEEDED_BCPROV_SOURCES" == "" \
    -o "$UNNEEDED_BCPKIX_SOURCES" == "" -o "$NEEDED_BCPKIX_SOURCES" == "" ]; then
    die "Invalid bouncycastle.config; see README.android for more information"
  fi

  declare -r command=$1
  shift || usage "No command specified. Try import, regenerate, or generate."
  if [ "$command" = "import" ]; then
    declare -r bcprov_tar=$1
    shift || usage "No tar file specified."
    declare -r bcpkix_tar=`echo $bcprov_tar | sed s/bcprov/bcpkix/`
    import $bcprov_tar $BOUNCYCASTLE_BCPROV_DIR $BOUNCYCASTLE_BCPROV_DIR_ORIG bcprov "$BOUNCYCASTLE_BCPROV_PATCHES" "$NEEDED_BCPROV_SOURCES" "$UNNEEDED_BCPROV_SOURCES"
    import $bcpkix_tar $BOUNCYCASTLE_BCPKIX_DIR $BOUNCYCASTLE_BCPKIX_DIR_ORIG bcpkix "$BOUNCYCASTLE_BCPKIX_PATCHES" "$NEEDED_BCPKIX_SOURCES" "$UNNEEDED_BCPKIX_SOURCES"
  elif [ "$command" = "regenerate" ]; then
    declare -r patch=$1
    shift || usage "No patch file specified."
    if [[ $BOUNCYCASTLE_BCPROV_PATCHES == *$patch* ]]; then
      [ -d $BOUNCYCASTLE_BCPROV_DIR ] || usage "$BOUNCYCASTLE_BCPROV_DIR not found, did you mean to use generate?"
      [ -d $BOUNCYCASTLE_BCPROV_DIR_ORIG ] || usage "$BOUNCYCASTLE_BCPROV_DIR_ORIG not found, did you mean to use generate?"
      regenerate $patch $BOUNCYCASTLE_BCPROV_DIR $BOUNCYCASTLE_BCPROV_DIR_ORIG
    elif [[ $BOUNCYCASTLE_BCPKIX_PATCHES == *$patch* ]]; then
      [ -d $BOUNCYCASTLE_BCPKIX_DIR ] || usage "$BOUNCYCASTLE_BCPROV_DIR not found, did you mean to use generate?"
      [ -d $BOUNCYCASTLE_BCPKIX_DIR_ORIG ] || usage "$BOUNCYCASTLE_BCPKIX_DIR_ORIG not found, did you mean to use generate?"
      regenerate $patch $BOUNCYCASTLE_BCPKIX_DIR $BOUNCYCASTLE_BCPKIX_DIR_ORIG
    else
      usage "Unknown patch file $patch specified"
    fi
  elif [ "$command" = "generate" ]; then
    declare -r patch=$1
    shift || usage "No patch file specified."
    declare -r bcprov_tar=$1
    shift || usage "No tar file specified."
    declare -r bcpkix_tar=`echo $bcprov_tar | sed s/bcprov/bcpkix/`
    if [[ $BOUNCYCASTLE_BCPROV_PATCHES == *$patch* ]]; then
      generate $patch $bcprov_tar $BOUNCYCASTLE_BCPROV_DIR $BOUNCYCASTLE_BCPROV_DIR_ORIG bcprov "$BOUNCYCASTLE_BCPROV_PATCHES" "$NEEDED_BCPROV_SOURCES" "$UNNEEDED_BCPROV_SOURCES"
    elif [[ $BOUNCYCASTLE_BCPKIX_PATCHES == *$patch* ]]; then
      generate $patch $bcpkix_tar $BOUNCYCASTLE_BCPKIX_DIR $BOUNCYCASTLE_BCPKIX_DIR_ORIG bcpkix "$BOUNCYCASTLE_BCPKIX_PATCHES" "$NEEDED_BCPKIX_SOURCES" "$UNNEEDED_BCPKIX_SOURCES"
    else
      usage "Unknown patch file $patch specified"
    fi
  else
    usage "Unknown command specified $command. Try import, regenerate, or generate."
  fi
}

function import() {
  declare -r bouncycastle_source=$1
  declare -r bouncycastle_dir=$2
  declare -r bouncycastle_dir_orig=$3
  declare -r bouncycastle_out_dir=$4
  declare -r bouncycastle_patches=$5
  declare -r needed_sources=$6
  declare -r unneeded_sources=$7

  untar $bouncycastle_source $bouncycastle_dir $bouncycastle_dir_orig "$unneeded_sources"
  applypatches $bouncycastle_dir "$bouncycastle_patches" "$unneeded_sources"

  cd $bouncycastle_dir

  sed 's/<p>/& <BR>/g' LICENSE.html | html2text -width 102 -nobs -ascii > ../NOTICE
  touch ../MODULE_LICENSE_BSD_LIKE

  cd ..

  rm -r $bouncycastle_out_dir/src
  mkdir -p $bouncycastle_out_dir/src/main/java/
  for i in $needed_sources; do
    echo "Updating $i"
    mv $bouncycastle_dir/$i $bouncycastle_out_dir/src/main/java/
  done

  cleantar $bouncycastle_dir $bouncycastle_dir_orig
}

function regenerate() {
  declare -r patch=$1
  declare -r bouncycastle_dir=$2
  declare -r bouncycastle_dir_orig=$3

  generatepatch $patch $bouncycastle_dir $bouncycastle_dir_orig
}

function update_timestamps() {
  declare -r git_dir="$1"
  declare -r target_dir="$2"

  echo -n "Restoring timestamps for ${target_dir}... "

  find "$git_dir" -type f -print0 | while IFS= read -r -d $'\0' file; do
    file_rev="$(git rev-list -n 1 HEAD "$file")"
    if [ "$file_rev" == "" ]; then
      echo
      echo -n "WARNING: No file revision for file $file..."
      continue
    fi
    file_time="$(git show --pretty=format:%ai --abbrev-commit "$file_rev" | head -n 1)"
    touch -d "$file_time" "${target_dir}${file#$git_dir}"
  done

  echo "done."
}

function generate() {
  declare -r patch=$1
  declare -r bouncycastle_source=$2
  declare -r bouncycastle_dir=$3
  declare -r bouncycastle_dir_orig=$4
  declare -r bouncycastle_out_dir=$5
  declare -r bouncycastle_patches=$6
  declare -r needed_sources=$7
  declare -r unneeded_sources=$8

  untar $bouncycastle_source $bouncycastle_dir $bouncycastle_dir_orig "$unneeded_sources"
  applypatches $bouncycastle_dir "$bouncycastle_patches" "$unneeded_sources"

  for i in $needed_sources; do
    echo "Restoring $i"
    rm -r $bouncycastle_dir/$i
    cp -rf $bouncycastle_out_dir/src/main/java/$i $bouncycastle_dir/$i
    update_timestamps $bouncycastle_out_dir/src/main/java/$i $bouncycastle_dir/$i
  done

  generatepatch $patch $bouncycastle_dir $bouncycastle_dir_orig
  cleantar $bouncycastle_dir $bouncycastle_dir_orig
}

function untar() {
  declare -r bouncycastle_source=$1
  declare -r bouncycastle_dir=$2
  declare -r bouncycastle_dir_orig=$3
  declare -r unneeded_sources=$4

  # Remove old source
  cleantar $bouncycastle_dir $bouncycastle_dir_orig

  # Process new source
  tar -zxf $bouncycastle_source
  mv $bouncycastle_dir $bouncycastle_dir_orig
  find $bouncycastle_dir_orig -type f -print0 | xargs -0 chmod a-w
  (cd $bouncycastle_dir_orig && unzip -q src.zip)
  tar -zxf $bouncycastle_source
  (cd $bouncycastle_dir && unzip -q src.zip)

  # Prune unnecessary sources
  echo "Removing $unneeded_sources"
  (cd $bouncycastle_dir_orig && rm -rf $unneeded_sources)
  (cd $bouncycastle_dir      && rm -r  $unneeded_sources)
}

function cleantar() {
  declare -r bouncycastle_dir=$1
  declare -r bouncycastle_dir_orig=$2

  rm -rf $bouncycastle_dir_orig
  rm -rf $bouncycastle_dir
}

function applypatches () {
  declare -r bouncycastle_dir=$1
  declare -r bouncycastle_patches=$2
  declare -r unneeded_sources=$3

  cd $bouncycastle_dir

  # Apply appropriate patches
  for i in $bouncycastle_patches; do
    echo "Applying patch $i"
    patch -p1 --merge < ../$i || die "Could not apply patches/$i. Fix source and run: $0 regenerate $i"

    # make sure no unneeded sources got into the patch
    problem=0
    for s in $unneeded_sources; do
      if [ -e $s ]; then
        echo Unneeded source $s restored by patch $i
        problem=1
      fi
    done
    if [ $problem = 1 ]; then
      exit 1
    fi
  done

  # Cleanup patch output
  find . -type f -name "*.orig" -print0 | xargs -0 rm -f

  cd ..
}

function generatepatch() {
  declare -r patch=$1
  declare -r bouncycastle_dir=$2
  declare -r bouncycastle_dir_orig=$3

  # Cleanup stray files before generating patch
  find $bouncycastle_dir -type f -name "*.orig" -print0 | xargs -0 rm -f
  find $bouncycastle_dir -type f -name "*~" -print0 | xargs -0 rm -f

  rm -f $patch
  LC_ALL=C TZ=UTC0 diff -Naur $bouncycastle_dir_orig $bouncycastle_dir >> $patch && die "ERROR: No diff for patch $path in file $i"
  echo "Generated patch $patch"
}

main $@