Home | History | Annotate | Download | only in scrypt
      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