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 ] || 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 sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' 171 } 172 173 function print_autogenerated_header() { 174 echo "// Auto-generated - DO NOT EDIT!" 175 echo "// To regenerate, edit scrypt.config, then run:" 176 echo "// ./import_scrypt.sh import /path/to/scrypt-$SCRYPT_VERSION.tar.gz" 177 echo "//" 178 } 179 180 # Return the value of a computed variable name. 181 # E.g.: 182 # FOO=foo 183 # BAR=bar 184 # echo $(var_value FOO_$BAR) -> prints the value of ${FOO_bar} 185 # $1: Variable name 186 # Out: variable value 187 var_value() { 188 # Note: don't use 'echo' here, because it's sensitive to values 189 # that begin with an underscore (e.g. "-n") 190 eval printf \"%s\\n\" \$$1 191 } 192 193 # Same as var_value, but returns sorted output without duplicates. 194 # $1: Variable name 195 # Out: variable value (if space-separated list, sorted with no duplicates) 196 var_sorted_value() { 197 uniq_sort $(var_value $1) 198 } 199 200 # $1: Property name 201 # $2: Indent 202 # $3: Values 203 print_list_in_bp() { 204 declare -r indent="$1" 205 shift 206 declare -r name="$1" 207 shift 208 209 if [ -n "$*" ]; then 210 echo "${indent}${name}: [" 211 for value in "$@"; do 212 echo "${indent} \"${value}\"," 213 done 214 echo "${indent}]," 215 fi 216 } 217 218 # Print an architecture-specific section 219 # $1: Arch 220 # $2: Arch variant 221 print_arch_section_in_bp() { 222 declare -r arch="$1" 223 declare -r variant="$2" 224 225 declare -r srcs="$(var_sorted_value SCRYPT_SOURCES_${arch})" 226 declare -r exclude_srcs="$(var_sorted_value SCRYPT_SOURCES_EXCLUDES_${arch})" 227 228 declare -r srcs_variant="$(var_sorted_value SCRYPT_SOURCES_${arch}_${variant})" 229 declare -r exclude_srcs_variant="$(var_sorted_value SCRYPT_SOURCES_EXCLUDES_${arch}_${variant})" 230 231 if [ -n "${srcs}${exclude_srcs}${srcs_variant}${exclude_srcs_variant}" ]; then 232 echo " ${arch}: {" 233 234 print_list_in_bp " " "srcs" ${srcs} 235 print_list_in_bp " " "exclude_srcs" ${exclude_srcs} 236 237 if [ -n "${src_variant}${exclude_srcs_variant}" ]; then 238 echo " ${variant}: {" 239 print_list_in_bp " " "srcs" ${srcs_variant} 240 print_list_in_bp " " "exclude_srcs" ${exclude_srcs_variant} 241 echo " }," 242 fi 243 244 echo " }," 245 fi 246 } 247 248 # Generate sources.bp from scrypt.config 249 # 250 # $1: Target file name. (e.g. sources.bp) 251 function generate_android_bp() { 252 declare -r output="$1" 253 254 # Extract cflags from upstream `./configure` script 255 cd $SCRYPT_DIR 256 257 ./configure $CONFIGURE_ARGS 258 259 declare -r tmpfile=$(mktemp) 260 (grep -e -D Makefile | grep -v CONFIGURE_ARGS= | grep -v OPTIONS=) > $tmpfile 261 262 declare -r ac_cflags=$(filter_by_egrep "^-D" $(grep -e "^CFLAG=" $tmpfile)) 263 declare -r ac_depflags=$(filter_by_egrep "^-D" $(grep -e "^DEPFLAG=" $tmpfile)) 264 rm -f $tmpfile 265 266 cd .. 267 268 # Generate sources.bp 269 echo "Generating $(basename $output)" 270 ( 271 print_autogenerated_header 272 273 cat <<__EOF__ 274 275 // 276 // Copyright (C) 2017 The Android Open Source Project 277 // 278 // Licensed under the Apache License, Version 2.0 (the "License"); 279 // you may not use this file except in compliance with the License. 280 // You may obtain a copy of the License at 281 // 282 // http://www.apache.org/licenses/LICENSE-2.0 283 // 284 // Unless required by applicable law or agreed to in writing, software 285 // distributed under the License is distributed on an "AS IS" BASIS, 286 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 287 // See the License for the specific language governing permissions and 288 // limitations under the License. 289 // 290 291 cc_defaults { 292 name: "libscrypt_sources", 293 294 __EOF__ 295 296 print_list_in_bp " " "cflags" \ 297 $(var_sorted_value SCRYPT_CFLAGS) ${ac_cflags} ${ac_depflags} 298 echo 299 300 print_list_in_bp " " "export_include_dirs" \ 301 $(var_sorted_value SCRYPT_EXPORT_C_INCLUDE_DIRS) 302 echo 303 304 print_list_in_bp " " "local_include_dirs" \ 305 $(var_sorted_value SCRYPT_INCLUDES) 306 echo 307 308 print_list_in_bp " " "srcs" $(var_sorted_value SCRYPT_SOURCES) 309 echo 310 311 echo " arch: {" 312 313 print_arch_section_in_bp "arm" "neon" 314 print_arch_section_in_bp "arm64" 315 print_arch_section_in_bp "x86" 316 print_arch_section_in_bp "x86_64" 317 print_arch_section_in_bp "mips" 318 print_arch_section_in_bp "mips64" 319 320 cat <<__EOF__ 321 }, 322 } 323 __EOF__ 324 ) > "$output" 325 } 326 327 function import() { 328 declare -r SCRYPT_SOURCE=$1 329 330 untar $SCRYPT_SOURCE readonly 331 applypatches $SCRYPT_DIR 332 333 cd $SCRYPT_DIR/.. 334 335 touch MODULE_LICENSE_BSD_LIKE 336 337 generate_android_bp "sources.bp" 338 339 # Prune unnecessary sources 340 prune 341 342 NEEDED_SOURCES="$NEEDED_SOURCES" 343 for i in $NEEDED_SOURCES; do 344 echo "Updating $i" 345 rm -r $i 346 mv $SCRYPT_DIR/$i . 347 done 348 349 cleantar 350 } 351 352 function regenerate() { 353 declare -r patch=$1 354 355 generatepatch $patch 356 } 357 358 function generate() { 359 declare -r patch=$1 360 declare -r SCRYPT_SOURCE=$2 361 362 untar $SCRYPT_SOURCE 363 applypatches $SCRYPT_DIR_ORIG $patch 364 prune 365 366 for i in $NEEDED_SOURCES; do 367 echo "Restoring $i" 368 rm -rf $SCRYPT_DIR/$i 369 cp -rf $i $SCRYPT_DIR/$i 370 done 371 372 generatepatch $patch 373 cleantar 374 } 375 376 # Find all files in a sub-directory that are encoded in ISO-8859 377 # $1: Directory. 378 # Out: list of files in $1 that are encoded as ISO-8859. 379 function find_iso8859_files() { 380 find $1 -type f -print0 | xargs -0 file | fgrep "ISO-8859" | cut -d: -f1 381 } 382 383 # Convert all ISO-8859 files in a given subdirectory to UTF-8 384 # $1: Directory name 385 function convert_iso8859_to_utf8() { 386 declare -r iso_files=$(find_iso8859_files "$1") 387 for iso_file in $iso_files; do 388 iconv --from-code iso-8859-1 --to-code utf-8 $iso_file > $iso_file.tmp 389 rm -f $iso_file 390 mv $iso_file.tmp $iso_file 391 done 392 } 393 394 function untar() { 395 declare -r SCRYPT_SOURCE=$1 396 declare -r readonly=$2 397 398 # Remove old source 399 cleantar 400 401 # Process new source 402 tar -zxf $SCRYPT_SOURCE 403 convert_iso8859_to_utf8 $SCRYPT_DIR 404 cp -rfP $SCRYPT_DIR $SCRYPT_DIR_ORIG 405 if [ ! -z $readonly ]; then 406 find $SCRYPT_DIR_ORIG -type f -print0 | xargs -0 chmod a-w 407 fi 408 } 409 410 function prune() { 411 echo "Removing $UNNEEDED_SOURCES" 412 (cd $SCRYPT_DIR_ORIG && rm -rf $UNNEEDED_SOURCES) 413 (cd $SCRYPT_DIR && rm -r $UNNEEDED_SOURCES) 414 } 415 416 function cleantar() { 417 rm -rf $SCRYPT_DIR_ORIG 418 rm -rf $SCRYPT_DIR 419 } 420 421 function applypatches () { 422 declare -r dir=$1 423 declare -r skip_patch=$2 424 425 cd $dir 426 427 # Apply appropriate patches 428 for i in $SCRYPT_PATCHES; do 429 if [ ! "$skip_patch" = "patches/$i" ]; then 430 echo "Applying patch $i" 431 patch -p1 --merge < ../patches/$i || die "Could not apply patches/$i. Fix source and run: $0 regenerate patches/$i" 432 else 433 echo "Skiping patch $i" 434 fi 435 436 done 437 438 # Cleanup patch output 439 find . \( -type f -o -type l \) -name "*.orig" -print0 | xargs -0 rm -f 440 441 cd .. 442 } 443 444 function generatepatch() { 445 declare -r patch=$1 446 447 # Cleanup stray files before generating patch 448 find $SCRYPT_DIR -type f -name "*.orig" -print0 | xargs -0 rm -f 449 find $SCRYPT_DIR -type f -name "*~" -print0 | xargs -0 rm -f 450 451 declare -r variable_name=SCRYPT_PATCHES_`basename $patch .patch | sed s/-/_/`_SOURCES 452 # http://tldp.org/LDP/abs/html/ivr.html 453 eval declare -r sources=\$$variable_name 454 rm -f $patch 455 touch $patch 456 for i in $sources; do 457 LC_ALL=C TZ=UTC0 diff -aupN $SCRYPT_DIR_ORIG/$i $SCRYPT_DIR/$i >> $patch && die "ERROR: No diff for patch $path in file $i" 458 done 459 echo "Generated patch $patch" 460 echo "NOTE To make sure there are not unwanted changes from conflicting patches, be sure to review the generated patch." 461 } 462 463 main $@ 464