1 #!/bin/bash 2 # 3 # Copyright (C) 2009 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 scrypt (http://www.tarsnap.com/scrypt/) into the 20 # Android source tree. To run, (1) fetch the appropriate tarball from the scrypt repository, 21 # (2) check the gpg/pgp signature, and then (3) run: 22 # ./import_scrypt.sh import scrypt-*.tar.gz 23 # 24 # IMPORTANT: See README.android for additional details. 25 26 # turn on exit on error as well as a warning when it happens 27 set -e 28 set -x 29 trap "echo WARNING: Exiting on non-zero subprocess exit code" ERR; 30 31 # Ensure consistent sorting order / tool output. 32 export LANG=C 33 export LC_ALL=C 34 35 export DIRNAME=$(dirname $0) 36 37 function die() { 38 declare -r message=$1 39 40 echo $message 41 exit 1 42 } 43 44 function usage() { 45 declare -r message=$1 46 47 if [ ! "$message" = "" ]; then 48 echo $message 49 fi 50 echo "Usage:" 51 echo " ./import_scrypt.sh import </path/to/scrypt-*.tar.gz>" 52 echo " ./import_scrypt.sh regenerate <patch/*.patch>" 53 echo " ./import_scrypt.sh generate <patch/*.patch> </path/to/scrypt-*.tar.gz>" 54 exit 1 55 } 56 57 function main() { 58 if [ ! -d patches ]; then 59 die "scrypt patch directory patches/ not found" 60 fi 61 62 if [ ! -f scrypt.version ]; then 63 die "scrypt.version not found" 64 fi 65 66 source $DIRNAME/scrypt.version 67 if [ "$SCRYPT_VERSION" == "" ]; then 68 die "Invalid scrypt.version; see README.android for more information" 69 fi 70 71 SCRYPT_DIR=scrypt-$SCRYPT_VERSION 72 SCRYPT_DIR_ORIG=$SCRYPT_DIR.orig 73 74 if [ ! -f scrypt.config ]; then 75 die "scrypt.config not found" 76 fi 77 78 source $DIRNAME/scrypt.config 79 if [ "$CONFIGURE_ARGS" == "" -o "$UNNEEDED_SOURCES" == "" -o "$NEEDED_SOURCES" == "" ]; then 80 die "Invalid scrypt.config; see README.android for more information" 81 fi 82 83 declare -r command=$1 84 shift || usage "No command specified. Try import, regenerate, or generate." 85 if [ "$command" = "import" ]; then 86 declare -r tar=$1 87 shift || usage "No tar file specified." 88 import $tar 89 elif [ "$command" = "regenerate" ]; then 90 declare -r patch=$1 91 shift || usage "No patch file specified." 92 [ -d $SCRYPT_DIR ] || usage "$SCRYPT_DIR not found, did you mean to use generate?" 93 [ -d $SCRYPT_DIR_ORIG_ORIG ] || usage "$SCRYPT_DIR_ORIG not found, did you mean to use generate?" 94 regenerate $patch 95 elif [ "$command" = "generate" ]; then 96 declare -r patch=$1 97 shift || usage "No patch file specified." 98 declare -r tar=$1 99 shift || usage "No tar file specified." 100 generate $patch $tar 101 else 102 usage "Unknown command specified $command. Try import, regenerate, or generate." 103 fi 104 } 105 106 # Compute the name of an assembly source file generated by one of the 107 # gen_asm_xxxx() functions below. The logic is the following: 108 # - if "$2" is not empty, output it directly 109 # - otherwise, change the file extension of $1 from .pl to .S and output 110 # it. 111 # Usage: default_asm_file "$1" "$2" 112 # or default_asm_file "$@" 113 # 114 # $1: generator path (perl script) 115 # $2: optional output file name. 116 function default_asm_file () { 117 if [ "$2" ]; then 118 echo "$2" 119 else 120 echo "${1%%.pl}.S" 121 fi 122 } 123 124 # Generate an ARM assembly file. 125 # $1: generator (perl script) 126 # $2: [optional] output file name 127 function gen_asm_arm () { 128 local OUT 129 OUT=$(default_asm_file "$@") 130 perl "$1" > "$OUT" 131 } 132 133 function gen_asm_mips () { 134 local OUT 135 OUT=$(default_asm_file "$@") 136 # The perl scripts expect to run the target compiler as $CC to determine 137 # the endianess of the target. Setting CC to true is a hack that forces the scripts 138 # to generate little endian output 139 CC=true perl "$1" o32 > "$OUT" 140 } 141 142 function gen_asm_x86 () { 143 local OUT 144 OUT=$(default_asm_file "$@") 145 perl "$1" elf -fPIC > "$OUT" 146 } 147 148 function gen_asm_x86_64 () { 149 local OUT 150 OUT=$(default_asm_file "$@") 151 perl "$1" elf "$OUT" > "$OUT" 152 } 153 154 155 # Filter all items in a list that match a given pattern. 156 # $1: space-separated list 157 # $2: egrep pattern. 158 # Out: items in $1 that match $2 159 function filter_by_egrep() { 160 declare -r pattern=$1 161 shift 162 echo "$@" | tr ' ' '\n' | grep -e "$pattern" | tr '\n' ' ' 163 } 164 165 # Sort and remove duplicates in a space-separated list 166 # $1: space-separated list 167 # Out: new space-separated list 168 function uniq_sort () { 169 echo "$@" | tr ' ' '\n' | sort -u | tr '\n' ' ' 170 } 171 172 function print_autogenerated_header() { 173 echo "# Auto-generated - DO NOT EDIT!" 174 echo "# To regenerate, edit scrypt.config, then run:" 175 echo "# ./import_scrypt.sh import /path/to/scrypt-$SCRYPT_VERSION.tar.gz" 176 echo "#" 177 } 178 179 function generate_build_config_mk() { 180 ./configure $CONFIGURE_ARGS 181 #rm -f apps/CA.pl.bak crypto/scryptconf.h.bak 182 183 declare -r tmpfile=$(mktemp) 184 (grep -e -D Makefile | grep -v CONFIGURE_ARGS= | grep -v OPTIONS=) > $tmpfile 185 186 declare -r cflags=$(filter_by_egrep "^-D" $(grep -e "^CFLAG=" $tmpfile)) 187 declare -r depflags=$(filter_by_egrep "^-D" $(grep -e "^DEPFLAG=" $tmpfile)) 188 rm -f $tmpfile 189 190 echo "Generating $(basename $1)" 191 ( 192 print_autogenerated_header 193 194 echo "scrypt_cflags := \\" 195 for cflag in $cflags $depflags; do 196 echo " $cflag \\" 197 done 198 echo "" 199 ) > $1 200 } 201 202 # Return the value of a computed variable name. 203 # E.g.: 204 # FOO=foo 205 # BAR=bar 206 # echo $(var_value FOO_$BAR) -> prints the value of ${FOO_bar} 207 # $1: Variable name 208 # Out: variable value 209 var_value() { 210 # Note: don't use 'echo' here, because it's sensitive to values 211 # that begin with an underscore (e.g. "-n") 212 eval printf \"%s\\n\" \$$1 213 } 214 215 # Same as var_value, but returns sorted output without duplicates. 216 # $1: Variable name 217 # Out: variable value (if space-separated list, sorted with no duplicates) 218 var_sorted_value() { 219 uniq_sort $(var_value $1) 220 } 221 222 # Print the definition of a given variable in a GNU Make build file. 223 # $1: Variable name (e.g. common_src_files) 224 # $2+: Variable value (e.g. list of sources) 225 print_vardef_in_mk() { 226 declare -r varname=$1 227 shift 228 if [ -z "$1" ]; then 229 echo "$varname :=" 230 else 231 echo "$varname := \\" 232 for src; do 233 echo " $src \\" 234 done 235 fi 236 echo "" 237 } 238 239 # Same as print_vardef_in_mk, but print a CFLAGS definition from 240 # a list of compiler defines. 241 # $1: Variable name (e.g. common_c_flags) 242 # $2: List of defines (e.g. SCRYPT_NO_DONKEYS ...) 243 print_defines_in_mk() { 244 declare -r varname=$1 245 shift 246 if [ -z "$1" ]; then 247 echo "$varname :=" 248 else 249 echo "$varname := \\" 250 for def; do 251 echo " -D$def \\" 252 done 253 fi 254 echo "" 255 } 256 257 # Generate a configuration file like Scrypt-config.mk 258 # This uses variable definitions from scrypt.config to build a config 259 # file that can compute the list of target- and host-specific sources / 260 # compiler flags for a given component. 261 # 262 # $1: Target file name. (e.g. Scrypt-config.mk) 263 function generate_config_mk() { 264 declare -r output="$1" 265 declare -r all_archs="arm arm_neon x86 x86_64 mips" 266 267 echo "Generating $(basename $output)" 268 ( 269 print_autogenerated_header 270 echo \ 271 "# Before including this file, the local Android.mk must define the following 272 # variables: 273 # 274 # local_c_flags 275 # local_c_includes 276 # local_additional_dependencies 277 # 278 # This script will define the following variables: 279 # 280 # target_c_flags 281 # target_c_includes 282 # target_src_files 283 # 284 # host_c_flags 285 # host_c_includes 286 # host_src_files 287 # 288 289 # Ensure these are empty. 290 unknown_arch_c_flags := 291 unknown_arch_src_files := 292 unknown_arch_exclude_files := 293 294 " 295 common_defines=$(var_sorted_value SCRYPT_DEFINES) 296 print_defines_in_mk common_c_flags $common_defines 297 298 common_sources=$(var_sorted_value SCRYPT_SOURCES) 299 print_vardef_in_mk common_src_files $common_sources 300 301 common_includes=$(var_sorted_value SCRYPT_INCLUDES) 302 print_vardef_in_mk common_c_includes $common_includes 303 304 for arch in $all_archs; do 305 arch_defines=$(var_sorted_value SCRYPT_DEFINES_${arch}) 306 print_defines_in_mk ${arch}_c_flags $arch_defines 307 308 arch_sources=$(var_sorted_value SCRYPT_SOURCES_${arch}) 309 print_vardef_in_mk ${arch}_src_files $arch_sources 310 311 arch_exclude_sources=$(var_sorted_value SCRYPT_SOURCES_EXCLUDES_${arch}) 312 print_vardef_in_mk ${arch}_exclude_files $arch_exclude_sources 313 314 done 315 316 echo "\ 317 target_arch := \$(TARGET_ARCH) 318 ifeq (\$(target_arch)-\$(TARGET_HAS_BIGENDIAN),mips-true) 319 target_arch := unknown_arch 320 endif 321 322 target_c_flags := \$(common_c_flags) \$(\$(target_arch)_c_flags) \$(local_c_flags) 323 target_c_includes := \$(addprefix external/scrypt/,\$(common_c_includes)) \$(local_c_includes) 324 target_src_files := \$(common_src_files) \$(\$(target_arch)_src_files) 325 target_src_files := \$(filter-out \$(\$(target_arch)_exclude_files), \$(target_src_files)) 326 327 # Hacks for ARM NEON support 328 ifeq (\$(target_arch),arm) 329 ifeq (\$(ARCH_ARM_HAVE_NEON),true) 330 target_c_flags += \$(arm_neon_c_flags) 331 target_src_files += \$(arm_neon_src_files) 332 target_src_files := \$(filter-out \$(arm_neon_exclude_files), \$(target_src_files)) 333 endif 334 endif 335 336 ifeq (\$(HOST_OS)-\$(HOST_ARCH),linux-x86) 337 host_arch := x86 338 else 339 host_arch := unknown_arch 340 endif 341 342 host_c_flags := \$(common_c_flags) \$(\$(host_arch)_c_flags) \$(local_c_flags) 343 host_c_includes := \$(addprefix external/scrypt/,\$(common_c_includes)) \$(local_c_includes) 344 host_src_files := \$(common_src_files) \$(\$(host_arch)_src_files) 345 host_src_files := \$(filter-out \$(\$(host_arch)_exclude_files), \$(host_src_files)) 346 347 local_additional_dependencies += \$(LOCAL_PATH)/$(basename $output) 348 " 349 350 ) > "$output" 351 } 352 353 function import() { 354 declare -r SCRYPT_SOURCE=$1 355 356 untar $SCRYPT_SOURCE readonly 357 applypatches $SCRYPT_DIR 358 359 cd $SCRYPT_DIR 360 361 generate_build_config_mk ../build-config.mk 362 363 touch ../MODULE_LICENSE_BSD_LIKE 364 365 cd .. 366 367 generate_config_mk Scrypt-config.mk 368 369 # Prune unnecessary sources 370 prune 371 372 NEEDED_SOURCES="$NEEDED_SOURCES" 373 for i in $NEEDED_SOURCES; do 374 echo "Updating $i" 375 rm -r $i 376 mv $SCRYPT_DIR/$i . 377 done 378 379 cleantar 380 } 381 382 function regenerate() { 383 declare -r patch=$1 384 385 generatepatch $patch 386 } 387 388 function generate() { 389 declare -r patch=$1 390 declare -r SCRYPT_SOURCE=$2 391 392 untar $SCRYPT_SOURCE 393 applypatches $SCRYPT_DIR_ORIG $patch 394 prune 395 396 for i in $NEEDED_SOURCES; do 397 echo "Restoring $i" 398 rm -r $SCRYPT_DIR/$i 399 cp -rf $i $SCRYPT_DIR/$i 400 done 401 402 generatepatch $patch 403 cleantar 404 } 405 406 # Find all files in a sub-directory that are encoded in ISO-8859 407 # $1: Directory. 408 # Out: list of files in $1 that are encoded as ISO-8859. 409 function find_iso8859_files() { 410 find $1 -type f -print0 | xargs -0 file | fgrep "ISO-8859" | cut -d: -f1 411 } 412 413 # Convert all ISO-8859 files in a given subdirectory to UTF-8 414 # $1: Directory name 415 function convert_iso8859_to_utf8() { 416 declare -r iso_files=$(find_iso8859_files "$1") 417 for iso_file in $iso_files; do 418 iconv --from-code iso-8859-1 --to-code utf-8 $iso_file > $iso_file.tmp 419 rm -f $iso_file 420 mv $iso_file.tmp $iso_file 421 done 422 } 423 424 function untar() { 425 declare -r SCRYPT_SOURCE=$1 426 declare -r readonly=$2 427 428 # Remove old source 429 cleantar 430 431 # Process new source 432 tar -zxf $SCRYPT_SOURCE 433 convert_iso8859_to_utf8 $SCRYPT_DIR 434 cp -rfP $SCRYPT_DIR $SCRYPT_DIR_ORIG 435 if [ ! -z $readonly ]; then 436 find $SCRYPT_DIR_ORIG -type f -print0 | xargs -0 chmod a-w 437 fi 438 } 439 440 function prune() { 441 echo "Removing $UNNEEDED_SOURCES" 442 (cd $SCRYPT_DIR_ORIG && rm -rf $UNNEEDED_SOURCES) 443 (cd $SCRYPT_DIR && rm -r $UNNEEDED_SOURCES) 444 } 445 446 function cleantar() { 447 rm -rf $SCRYPT_DIR_ORIG 448 rm -rf $SCRYPT_DIR 449 } 450 451 function applypatches () { 452 declare -r dir=$1 453 declare -r skip_patch=$2 454 455 cd $dir 456 457 # Apply appropriate patches 458 for i in $SCRYPT_PATCHES; do 459 if [ ! "$skip_patch" = "patches/$i" ]; then 460 echo "Applying patch $i" 461 patch -p1 --merge < ../patches/$i || die "Could not apply patches/$i. Fix source and run: $0 regenerate patches/$i" 462 else 463 echo "Skiping patch $i" 464 fi 465 466 done 467 468 # Cleanup patch output 469 find . \( -type f -o -type l \) -name "*.orig" -print0 | xargs -0 rm -f 470 471 cd .. 472 } 473 474 function generatepatch() { 475 declare -r patch=$1 476 477 # Cleanup stray files before generating patch 478 find $SCRYPT_DIR -type f -name "*.orig" -print0 | xargs -0 rm -f 479 find $SCRYPT_DIR -type f -name "*~" -print0 | xargs -0 rm -f 480 481 declare -r variable_name=SCRYPT_PATCHES_`basename $patch .patch | sed s/-/_/`_SOURCES 482 # http://tldp.org/LDP/abs/html/ivr.html 483 eval declare -r sources=\$$variable_name 484 rm -f $patch 485 touch $patch 486 for i in $sources; do 487 LC_ALL=C TZ=UTC0 diff -aup $SCRYPT_DIR_ORIG/$i $SCRYPT_DIR/$i >> $patch && die "ERROR: No diff for patch $path in file $i" 488 done 489 echo "Generated patch $patch" 490 echo "NOTE To make sure there are not unwanted changes from conflicting patches, be sure to review the generated patch." 491 } 492 493 main $@ 494