• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
27set -e
28set -x
29trap  "echo WARNING: Exiting on non-zero subprocess exit code" ERR;
30
31# Ensure consistent sorting order / tool output.
32export LANG=C
33export LC_ALL=C
34
35export DIRNAME=$(dirname $0)
36
37function die() {
38  declare -r message=$1
39
40  echo $message
41  exit 1
42}
43
44function 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
57function 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.
116function 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
127function gen_asm_arm () {
128  local OUT
129  OUT=$(default_asm_file "$@")
130  perl "$1" > "$OUT"
131}
132
133function 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
142function gen_asm_x86 () {
143  local OUT
144  OUT=$(default_asm_file "$@")
145  perl "$1" elf -fPIC > "$OUT"
146}
147
148function 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
159function 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
168function uniq_sort () {
169  echo "$@" | tr ' ' '\n' | sort -u | tr '\n' ' ' | \
170    sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
171}
172
173function 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
187var_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)
196var_sorted_value() {
197  uniq_sort $(var_value $1)
198}
199
200# $1: Property name
201# $2: Indent
202# $3: Values
203print_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
221print_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)
251function 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
291cc_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
327function 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
352function regenerate() {
353  declare -r patch=$1
354
355  generatepatch $patch
356}
357
358function 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.
379function 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
385function 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
394function 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
410function 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
416function cleantar() {
417  rm -rf $SCRYPT_DIR_ORIG
418  rm -rf $SCRYPT_DIR
419}
420
421function 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
444function 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
463main $@
464