#!/bin/bash # # Copyright (C) 2009 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 scrypt (http://www.tarsnap.com/scrypt/) into the # Android source tree. To run, (1) fetch the appropriate tarball from the scrypt repository, # (2) check the gpg/pgp signature, and then (3) run: # ./import_scrypt.sh import scrypt-*.tar.gz # # IMPORTANT: See README.android for additional details. # turn on exit on error as well as a warning when it happens set -e set -x trap "echo WARNING: Exiting on non-zero subprocess exit code" ERR; # Ensure consistent sorting order / tool output. export LANG=C export LC_ALL=C export DIRNAME=$(dirname $0) 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_scrypt.sh import " echo " ./import_scrypt.sh regenerate " echo " ./import_scrypt.sh generate " exit 1 } function main() { if [ ! -d patches ]; then die "scrypt patch directory patches/ not found" fi if [ ! -f scrypt.version ]; then die "scrypt.version not found" fi source $DIRNAME/scrypt.version if [ "$SCRYPT_VERSION" == "" ]; then die "Invalid scrypt.version; see README.android for more information" fi SCRYPT_DIR=scrypt-$SCRYPT_VERSION SCRYPT_DIR_ORIG=$SCRYPT_DIR.orig if [ ! -f scrypt.config ]; then die "scrypt.config not found" fi source $DIRNAME/scrypt.config if [ "$CONFIGURE_ARGS" == "" -o "$UNNEEDED_SOURCES" == "" -o "$NEEDED_SOURCES" == "" ]; then die "Invalid scrypt.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 tar=$1 shift || usage "No tar file specified." import $tar elif [ "$command" = "regenerate" ]; then declare -r patch=$1 shift || usage "No patch file specified." [ -d $SCRYPT_DIR ] || usage "$SCRYPT_DIR not found, did you mean to use generate?" [ -d $SCRYPT_DIR_ORIG ] || usage "$SCRYPT_DIR_ORIG not found, did you mean to use generate?" regenerate $patch elif [ "$command" = "generate" ]; then declare -r patch=$1 shift || usage "No patch file specified." declare -r tar=$1 shift || usage "No tar file specified." generate $patch $tar else usage "Unknown command specified $command. Try import, regenerate, or generate." fi } # Compute the name of an assembly source file generated by one of the # gen_asm_xxxx() functions below. The logic is the following: # - if "$2" is not empty, output it directly # - otherwise, change the file extension of $1 from .pl to .S and output # it. # Usage: default_asm_file "$1" "$2" # or default_asm_file "$@" # # $1: generator path (perl script) # $2: optional output file name. function default_asm_file () { if [ "$2" ]; then echo "$2" else echo "${1%%.pl}.S" fi } # Generate an ARM assembly file. # $1: generator (perl script) # $2: [optional] output file name function gen_asm_arm () { local OUT OUT=$(default_asm_file "$@") perl "$1" > "$OUT" } function gen_asm_mips () { local OUT OUT=$(default_asm_file "$@") # The perl scripts expect to run the target compiler as $CC to determine # the endianess of the target. Setting CC to true is a hack that forces the scripts # to generate little endian output CC=true perl "$1" o32 > "$OUT" } function gen_asm_x86 () { local OUT OUT=$(default_asm_file "$@") perl "$1" elf -fPIC > "$OUT" } function gen_asm_x86_64 () { local OUT OUT=$(default_asm_file "$@") perl "$1" elf "$OUT" > "$OUT" } # Filter all items in a list that match a given pattern. # $1: space-separated list # $2: egrep pattern. # Out: items in $1 that match $2 function filter_by_egrep() { declare -r pattern=$1 shift echo "$@" | tr ' ' '\n' | grep -e "$pattern" | tr '\n' ' ' } # Sort and remove duplicates in a space-separated list # $1: space-separated list # Out: new space-separated list function uniq_sort () { echo "$@" | tr ' ' '\n' | sort -u | tr '\n' ' ' | \ sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' } function print_autogenerated_header() { echo "// Auto-generated - DO NOT EDIT!" echo "// To regenerate, edit scrypt.config, then run:" echo "// ./import_scrypt.sh import /path/to/scrypt-$SCRYPT_VERSION.tar.gz" echo "//" } # Return the value of a computed variable name. # E.g.: # FOO=foo # BAR=bar # echo $(var_value FOO_$BAR) -> prints the value of ${FOO_bar} # $1: Variable name # Out: variable value var_value() { # Note: don't use 'echo' here, because it's sensitive to values # that begin with an underscore (e.g. "-n") eval printf \"%s\\n\" \$$1 } # Same as var_value, but returns sorted output without duplicates. # $1: Variable name # Out: variable value (if space-separated list, sorted with no duplicates) var_sorted_value() { uniq_sort $(var_value $1) } # $1: Property name # $2: Indent # $3: Values print_list_in_bp() { declare -r indent="$1" shift declare -r name="$1" shift if [ -n "$*" ]; then echo "${indent}${name}: [" for value in "$@"; do echo "${indent} \"${value}\"," done echo "${indent}]," fi } # Print an architecture-specific section # $1: Arch # $2: Arch variant print_arch_section_in_bp() { declare -r arch="$1" declare -r variant="$2" declare -r srcs="$(var_sorted_value SCRYPT_SOURCES_${arch})" declare -r exclude_srcs="$(var_sorted_value SCRYPT_SOURCES_EXCLUDES_${arch})" declare -r srcs_variant="$(var_sorted_value SCRYPT_SOURCES_${arch}_${variant})" declare -r exclude_srcs_variant="$(var_sorted_value SCRYPT_SOURCES_EXCLUDES_${arch}_${variant})" if [ -n "${srcs}${exclude_srcs}${srcs_variant}${exclude_srcs_variant}" ]; then echo " ${arch}: {" print_list_in_bp " " "srcs" ${srcs} print_list_in_bp " " "exclude_srcs" ${exclude_srcs} if [ -n "${src_variant}${exclude_srcs_variant}" ]; then echo " ${variant}: {" print_list_in_bp " " "srcs" ${srcs_variant} print_list_in_bp " " "exclude_srcs" ${exclude_srcs_variant} echo " }," fi echo " }," fi } # Generate sources.bp from scrypt.config # # $1: Target file name. (e.g. sources.bp) function generate_android_bp() { declare -r output="$1" # Extract cflags from upstream `./configure` script cd $SCRYPT_DIR ./configure $CONFIGURE_ARGS declare -r tmpfile=$(mktemp) (grep -e -D Makefile | grep -v CONFIGURE_ARGS= | grep -v OPTIONS=) > $tmpfile declare -r ac_cflags=$(filter_by_egrep "^-D" $(grep -e "^CFLAG=" $tmpfile)) declare -r ac_depflags=$(filter_by_egrep "^-D" $(grep -e "^DEPFLAG=" $tmpfile)) rm -f $tmpfile cd .. # Generate sources.bp echo "Generating $(basename $output)" ( print_autogenerated_header cat <<__EOF__ // // Copyright (C) 2017 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. // cc_defaults { name: "libscrypt_sources", __EOF__ print_list_in_bp " " "cflags" \ $(var_sorted_value SCRYPT_CFLAGS) ${ac_cflags} ${ac_depflags} echo print_list_in_bp " " "export_include_dirs" \ $(var_sorted_value SCRYPT_EXPORT_C_INCLUDE_DIRS) echo print_list_in_bp " " "local_include_dirs" \ $(var_sorted_value SCRYPT_INCLUDES) echo print_list_in_bp " " "srcs" $(var_sorted_value SCRYPT_SOURCES) echo echo " arch: {" print_arch_section_in_bp "arm" "neon" print_arch_section_in_bp "arm64" print_arch_section_in_bp "x86" print_arch_section_in_bp "x86_64" print_arch_section_in_bp "mips" print_arch_section_in_bp "mips64" cat <<__EOF__ }, } __EOF__ ) > "$output" } function import() { declare -r SCRYPT_SOURCE=$1 untar $SCRYPT_SOURCE readonly applypatches $SCRYPT_DIR cd $SCRYPT_DIR/.. touch MODULE_LICENSE_BSD_LIKE generate_android_bp "sources.bp" # Prune unnecessary sources prune NEEDED_SOURCES="$NEEDED_SOURCES" for i in $NEEDED_SOURCES; do echo "Updating $i" rm -r $i mv $SCRYPT_DIR/$i . done cleantar } function regenerate() { declare -r patch=$1 generatepatch $patch } function generate() { declare -r patch=$1 declare -r SCRYPT_SOURCE=$2 untar $SCRYPT_SOURCE applypatches $SCRYPT_DIR_ORIG $patch prune for i in $NEEDED_SOURCES; do echo "Restoring $i" rm -rf $SCRYPT_DIR/$i cp -rf $i $SCRYPT_DIR/$i done generatepatch $patch cleantar } # Find all files in a sub-directory that are encoded in ISO-8859 # $1: Directory. # Out: list of files in $1 that are encoded as ISO-8859. function find_iso8859_files() { find $1 -type f -print0 | xargs -0 file | fgrep "ISO-8859" | cut -d: -f1 } # Convert all ISO-8859 files in a given subdirectory to UTF-8 # $1: Directory name function convert_iso8859_to_utf8() { declare -r iso_files=$(find_iso8859_files "$1") for iso_file in $iso_files; do iconv --from-code iso-8859-1 --to-code utf-8 $iso_file > $iso_file.tmp rm -f $iso_file mv $iso_file.tmp $iso_file done } function untar() { declare -r SCRYPT_SOURCE=$1 declare -r readonly=$2 # Remove old source cleantar # Process new source tar -zxf $SCRYPT_SOURCE convert_iso8859_to_utf8 $SCRYPT_DIR cp -rfP $SCRYPT_DIR $SCRYPT_DIR_ORIG if [ ! -z $readonly ]; then find $SCRYPT_DIR_ORIG -type f -print0 | xargs -0 chmod a-w fi } function prune() { echo "Removing $UNNEEDED_SOURCES" (cd $SCRYPT_DIR_ORIG && rm -rf $UNNEEDED_SOURCES) (cd $SCRYPT_DIR && rm -r $UNNEEDED_SOURCES) } function cleantar() { rm -rf $SCRYPT_DIR_ORIG rm -rf $SCRYPT_DIR } function applypatches () { declare -r dir=$1 declare -r skip_patch=$2 cd $dir # Apply appropriate patches for i in $SCRYPT_PATCHES; do if [ ! "$skip_patch" = "patches/$i" ]; then echo "Applying patch $i" patch -p1 --merge < ../patches/$i || die "Could not apply patches/$i. Fix source and run: $0 regenerate patches/$i" else echo "Skiping patch $i" fi done # Cleanup patch output find . \( -type f -o -type l \) -name "*.orig" -print0 | xargs -0 rm -f cd .. } function generatepatch() { declare -r patch=$1 # Cleanup stray files before generating patch find $SCRYPT_DIR -type f -name "*.orig" -print0 | xargs -0 rm -f find $SCRYPT_DIR -type f -name "*~" -print0 | xargs -0 rm -f declare -r variable_name=SCRYPT_PATCHES_`basename $patch .patch | sed s/-/_/`_SOURCES # http://tldp.org/LDP/abs/html/ivr.html eval declare -r sources=\$$variable_name rm -f $patch touch $patch for i in $sources; do 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" done echo "Generated patch $patch" echo "NOTE To make sure there are not unwanted changes from conflicting patches, be sure to review the generated patch." } main $@