import_bouncycastle.sh revision aea1f1224e7ad62991b68c485f086abcb289f82b
1#!/bin/bash
2#
3# Copyright (C) 2010 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18#
19# This script imports new versions of Bouncy Castle
20# (http://bouncycastle.org) into the Android source tree.  To run, (1)
21# fetch the appropriate tarballs (bcprov and bcpkix) from the Bouncy
22# Castle repository, (2) check the checksum, and then (3) run:
23#   ./import_bouncycastle.sh import bcprov-jdk*-*.tar.gz
24#
25# IMPORTANT: See README.android for additional details.
26
27# turn on exit on error as well as a warning when it happens
28set -e
29trap  "echo WARNING: Exiting on non-zero subprocess exit code" ERR;
30
31function die() {
32  declare -r message=$1
33
34  echo $message
35  exit 1
36}
37
38function usage() {
39  declare -r message=$1
40
41  if [ ! "$message" = "" ]; then
42    echo $message
43  fi
44  echo "Usage:"
45  echo "  ./import_bouncycastle.sh import </path/to/bcprov-jdk*-*.tar.gz>"
46  echo "  ./import_bouncycastle.sh regenerate <patch/*.patch>"
47  echo "  ./import_bouncycastle.sh generate <patch/*.patch> </path/to/bcprov-jdk*-*.tar.gz>"
48  exit 1
49}
50
51function main() {
52  if [ ! -d patches ]; then
53    die "Bouncy Castle patch directory patches/ not found"
54  fi
55
56  if [ ! -f bouncycastle.version ]; then
57    die "bouncycastle.version not found"
58  fi
59
60  source bouncycastle.version
61  if [ "$BOUNCYCASTLE_JDK" == "" -o "$BOUNCYCASTLE_VERSION" == "" ]; then
62    die "Invalid bouncycastle.version; see README.android for more information"
63  fi
64
65  BOUNCYCASTLE_BCPROV_DIR=bcprov-jdk$BOUNCYCASTLE_JDK-$BOUNCYCASTLE_VERSION
66  BOUNCYCASTLE_BCPROV_DIR_ORIG=$BOUNCYCASTLE_BCPROV_DIR.orig
67
68  BOUNCYCASTLE_BCPKIX_DIR=bcpkix-jdk$BOUNCYCASTLE_JDK-$BOUNCYCASTLE_VERSION
69  BOUNCYCASTLE_BCPKIX_DIR_ORIG=$BOUNCYCASTLE_BCPKIX_DIR.orig
70
71  if [ ! -f bouncycastle.config ]; then
72    die "bouncycastle.config not found"
73  fi
74
75  source bouncycastle.config
76  if [ "$UNNEEDED_BCPROV_SOURCES" == "" -o "$NEEDED_BCPROV_SOURCES" == "" \
77    -o "$UNNEEDED_BCPKIX_SOURCES" == "" -o "$NEEDED_BCPKIX_SOURCES" == "" ]; then
78    die "Invalid bouncycastle.config; see README.android for more information"
79  fi
80
81  declare -r command=$1
82  shift || usage "No command specified. Try import, regenerate, or generate."
83  if [ "$command" = "import" ]; then
84    declare -r bcprov_tar=$1
85    shift || usage "No tar file specified."
86    declare -r bcpkix_tar=`echo $bcprov_tar | sed s/bcprov/bcpkix/`
87    import $bcprov_tar $BOUNCYCASTLE_BCPROV_DIR $BOUNCYCASTLE_BCPROV_DIR_ORIG bcprov "$BOUNCYCASTLE_BCPROV_PATCHES" "$NEEDED_BCPROV_SOURCES" "$UNNEEDED_BCPROV_SOURCES"
88    import $bcpkix_tar $BOUNCYCASTLE_BCPKIX_DIR $BOUNCYCASTLE_BCPKIX_DIR_ORIG bcpkix "$BOUNCYCASTLE_BCPKIX_PATCHES" "$NEEDED_BCPKIX_SOURCES" "$UNNEEDED_BCPKIX_SOURCES"
89  elif [ "$command" = "regenerate" ]; then
90    declare -r patch=$1
91    shift || usage "No patch file specified."
92    if [[ $BOUNCYCASTLE_BCPROV_PATCHES == *$patch* ]]; then
93      [ -d $BOUNCYCASTLE_BCPROV_DIR ] || usage "$BOUNCYCASTLE_BCPROV_DIR not found, did you mean to use generate?"
94      [ -d $BOUNCYCASTLE_BCPROV_DIR_ORIG ] || usage "$BOUNCYCASTLE_BCPROV_DIR_ORIG not found, did you mean to use generate?"
95      regenerate $patch $BOUNCYCASTLE_BCPROV_DIR $BOUNCYCASTLE_BCPROV_DIR_ORIG
96    elif [[ $BOUNCYCASTLE_BCPKIX_PATCHES == *$patch* ]]; then
97      [ -d $BOUNCYCASTLE_BCPKIX_DIR ] || usage "$BOUNCYCASTLE_BCPROV_DIR not found, did you mean to use generate?"
98      [ -d $BOUNCYCASTLE_BCPKIX_DIR_ORIG ] || usage "$BOUNCYCASTLE_BCPKIX_DIR_ORIG not found, did you mean to use generate?"
99      regenerate $patch $BOUNCYCASTLE_BCPKIX_DIR $BOUNCYCASTLE_BCPKIX_DIR_ORIG
100    else
101      usage "Unknown patch file $patch specified"
102    fi
103  elif [ "$command" = "generate" ]; then
104    declare -r patch=$1
105    shift || usage "No patch file specified."
106    declare -r bcprov_tar=$1
107    shift || usage "No tar file specified."
108    declare -r bcpkix_tar=`echo $bcprov_tar | sed s/bcprov/bcpkix/`
109    if [[ $BOUNCYCASTLE_BCPROV_PATCHES == *$patch* ]]; then
110      generate $patch $bcprov_tar $BOUNCYCASTLE_BCPROV_DIR $BOUNCYCASTLE_BCPROV_DIR_ORIG bcprov "$BOUNCYCASTLE_BCPROV_PATCHES" "$NEEDED_BCPROV_SOURCES" "$UNNEEDED_BCPROV_SOURCES"
111    elif [[ $BOUNCYCASTLE_BCPKIX_PATCHES == *$patch* ]]; then
112      generate $patch $bcpkix_tar $BOUNCYCASTLE_BCPKIX_DIR $BOUNCYCASTLE_BCPKIX_DIR_ORIG bcpkix "$BOUNCYCASTLE_BCPKIX_PATCHES" "$NEEDED_BCPKIX_SOURCES" "$UNNEEDED_BCPKIX_SOURCES"
113    else
114      usage "Unknown patch file $patch specified"
115    fi
116  else
117    usage "Unknown command specified $command. Try import, regenerate, or generate."
118  fi
119}
120
121function import() {
122  declare -r bouncycastle_source=$1
123  declare -r bouncycastle_dir=$2
124  declare -r bouncycastle_dir_orig=$3
125  declare -r bouncycastle_out_dir=$4
126  declare -r bouncycastle_patches=$5
127  declare -r needed_sources=$6
128  declare -r unneeded_sources=$7
129
130  untar $bouncycastle_source $bouncycastle_dir $bouncycastle_dir_orig "$unneeded_sources"
131  applypatches $bouncycastle_dir "$bouncycastle_patches" "$unneeded_sources"
132
133  cd $bouncycastle_dir
134
135  sed 's/<p>/& <BR>/g' LICENSE.html | html2text -width 102 -nobs -ascii > ../NOTICE
136  touch ../MODULE_LICENSE_BSD_LIKE
137
138  cd ..
139
140  rm -r $bouncycastle_out_dir/src
141  mkdir -p $bouncycastle_out_dir/src/main/java/
142  for i in $needed_sources; do
143    echo "Updating $i"
144    mv $bouncycastle_dir/$i $bouncycastle_out_dir/src/main/java/
145  done
146
147  cleantar $bouncycastle_dir $bouncycastle_dir_orig
148}
149
150function regenerate() {
151  declare -r patch=$1
152  declare -r bouncycastle_dir=$2
153  declare -r bouncycastle_dir_orig=$3
154
155  generatepatch $patch $bouncycastle_dir $bouncycastle_dir_orig
156}
157
158function update_timestamps() {
159  declare -r git_dir="$1"
160  declare -r target_dir="$2"
161
162  echo -n "Restoring timestamps for ${target_dir}... "
163
164  find "$git_dir" -type f -print0 | while IFS= read -r -d $'\0' file; do
165    file_rev="$(git rev-list -n 1 HEAD "$file")"
166    file_time="$(git show --pretty=format:%ai --abbrev-commit "$file_rev" | head -n 1)"
167    touch -d "$file_time" "${target_dir}${file#$git_dir}"
168  done
169
170  echo "done."
171}
172
173function generate() {
174  declare -r patch=$1
175  declare -r bouncycastle_source=$2
176  declare -r bouncycastle_dir=$3
177  declare -r bouncycastle_dir_orig=$4
178  declare -r bouncycastle_out_dir=$5
179  declare -r bouncycastle_patches=$6
180  declare -r needed_sources=$7
181  declare -r unneeded_sources=$8
182
183  untar $bouncycastle_source $bouncycastle_dir $bouncycastle_dir_orig "$unneeded_sources"
184  applypatches $bouncycastle_dir "$bouncycastle_patches" "$unneeded_sources"
185
186  for i in $needed_sources; do
187    echo "Restoring $i"
188    rm -r $bouncycastle_dir/$i
189    cp -rf $bouncycastle_out_dir/src/main/java/$i $bouncycastle_dir/$i
190    update_timestamps $bouncycastle_out_dir/src/main/java/$i $bouncycastle_dir/$i
191  done
192
193  generatepatch $patch $bouncycastle_dir $bouncycastle_dir_orig
194  cleantar $bouncycastle_dir $bouncycastle_dir_orig
195}
196
197function untar() {
198  declare -r bouncycastle_source=$1
199  declare -r bouncycastle_dir=$2
200  declare -r bouncycastle_dir_orig=$3
201  declare -r unneeded_sources=$4
202
203  # Remove old source
204  cleantar $bouncycastle_dir $bouncycastle_dir_orig
205
206  # Process new source
207  tar -zxf $bouncycastle_source
208  mv $bouncycastle_dir $bouncycastle_dir_orig
209  find $bouncycastle_dir_orig -type f -print0 | xargs -0 chmod a-w
210  (cd $bouncycastle_dir_orig && unzip -q src.zip)
211  tar -zxf $bouncycastle_source
212  (cd $bouncycastle_dir && unzip -q src.zip)
213
214  # Prune unnecessary sources
215  echo "Removing $unneeded_sources"
216  (cd $bouncycastle_dir_orig && rm -rf $unneeded_sources)
217  (cd $bouncycastle_dir      && rm -r  $unneeded_sources)
218}
219
220function cleantar() {
221  declare -r bouncycastle_dir=$1
222  declare -r bouncycastle_dir_orig=$2
223
224  rm -rf $bouncycastle_dir_orig
225  rm -rf $bouncycastle_dir
226}
227
228function applypatches () {
229  declare -r bouncycastle_dir=$1
230  declare -r bouncycastle_patches=$2
231  declare -r unneeded_sources=$3
232
233  cd $bouncycastle_dir
234
235  # Apply appropriate patches
236  for i in $bouncycastle_patches; do
237    echo "Applying patch $i"
238    patch -p1 < ../$i || die "Could not apply patches/$i. Fix source and run: $0 regenerate $i"
239
240    # make sure no unneeded sources got into the patch
241    problem=0
242    for s in $unneeded_sources; do
243      if [ -e $s ]; then
244        echo Unneeded source $s restored by patch $i
245        problem=1
246      fi
247    done
248    if [ $problem = 1 ]; then
249      exit 1
250    fi
251  done
252
253  # Cleanup patch output
254  find . -type f -name "*.orig" -print0 | xargs -0 rm -f
255
256  cd ..
257}
258
259function generatepatch() {
260  declare -r patch=$1
261  declare -r bouncycastle_dir=$2
262  declare -r bouncycastle_dir_orig=$3
263
264  # Cleanup stray files before generating patch
265  find $bouncycastle_dir -type f -name "*.orig" -print0 | xargs -0 rm -f
266  find $bouncycastle_dir -type f -name "*~" -print0 | xargs -0 rm -f
267
268  rm -f $patch
269  LC_ALL=C TZ=UTC0 diff -Naur $bouncycastle_dir_orig $bouncycastle_dir >> $patch && die "ERROR: No diff for patch $path in file $i"
270  echo "Generated patch $patch"
271}
272
273main $@
274