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 ] || 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