extract_files: Add extract2() function
New devices have more than one partition, and it's very
cumbersome to try to extract all the blobs for different
partitions from one directory. Adding multi-directory support
breaks the existing single directory method, so a new function
was born. Also, have native support for SAR system image mounts
so you can do some argument simplification in the device
extract-files.sh
Change-Id: I94925897690fc23816a28c9cdb34fb11e46635b8
diff --git a/build/tools/extract_utils.sh b/build/tools/extract_utils.sh
index 9402de6..7bcfc01 100755
--- a/build/tools/extract_utils.sh
+++ b/build/tools/extract_utils.sh
@@ -1380,6 +1380,240 @@
}
#
+# extract2:
+#
+# Positional parameters:
+# $1: file containing the list of items to extract (aka proprietary-files.txt)
+#
+# Non-positional parameters (coming after $2):
+# --section: selects the portion to parse and extracts from proprietary-files.txt
+# --kang: if present, this option will activate the printing of hashes for the
+# extracted blobs. Useful with --section for subsequent pinning of
+# blobs taken from other origins.
+#
+function extract2() {
+ # Consume positional parameters
+ local PROPRIETARY_FILES_TXT="$1"; shift
+ local SECTION=""
+ local KANG=false
+
+ # Consume optional, non-positional parameters
+ while [ "$#" -gt 0 ]; do
+ case "$1" in
+ --adb)
+ ADB=true
+ ;;
+ --system)
+ SYSTEM_SRC="$2"; shift
+ ;;
+ --vendor)
+ VENDOR_SRC="$2"; shift
+ ;;
+ --odm)
+ ODM_SRC="$2"; shift
+ ;;
+ --product)
+ PRODUCT_SRC="$2"; shift
+ ;;
+ -s|--section)
+ SECTION="$2"; shift
+ ;;
+ -k|--kang)
+ KANG=true
+ DISABLE_PINNING=1
+ ;;
+ esac
+ shift
+ done
+
+ if [ -z "$ADB" ] || [ -z "$SYSTEM_SRC" && -z "$VENDOR_SRC" && -z "$ODM_SRC" && -z "$PRODUCT_SRC" ]; then
+ echo "No sources set! You must select --adb or pass paths to partition dumps."
+ exit 1
+ fi
+
+ if [ -z "$OUTDIR" ]; then
+ echo "Output dir not set!"
+ exit 1
+ fi
+
+ parse_file_list "${PROPRIETARY_FILES_TXT}" "${SECTION}"
+
+ # Allow failing, so we can try $DEST and/or $FILE
+ set +e
+
+ local FILELIST=( ${PRODUCT_COPY_FILES_LIST[@]} ${PRODUCT_PACKAGES_LIST[@]} )
+ local HASHLIST=( ${PRODUCT_COPY_FILES_HASHES[@]} ${PRODUCT_PACKAGES_HASHES[@]} )
+ local FIXUP_HASHLIST=( ${PRODUCT_COPY_FILES_FIXUP_HASHES[@]} ${PRODUCT_PACKAGES_FIXUP_HASHES[@]} )
+ local PRODUCT_COPY_FILES_COUNT=${#PRODUCT_COPY_FILES_LIST[@]}
+ local COUNT=${#FILELIST[@]}
+ local OUTPUT_ROOT="$OMNI_ROOT"/"$OUTDIR"/proprietary
+ local OUTPUT_TMP="$TMPDIR"/"$OUTDIR"/proprietary
+
+ if [ "$ADB" = true ]; then
+ init_adb_connection
+ fi
+
+ if [ "$VENDOR_STATE" -eq "0" ]; then
+ echo "Cleaning output directory ($OUTPUT_ROOT).."
+ rm -rf "${OUTPUT_TMP:?}"
+ mkdir -p "${OUTPUT_TMP:?}"
+ if [ -d "$OUTPUT_ROOT" ]; then
+ mv "${OUTPUT_ROOT:?}/"* "${OUTPUT_TMP:?}/"
+ fi
+ VENDOR_STATE=1
+ fi
+
+ echo "Extracting ${COUNT} files in ${PROPRIETARY_FILES_TXT} from ${SRC}:"
+
+ for (( i=1; i<COUNT+1; i++ )); do
+
+ local SPEC_SRC_FILE=$(src_file "${FILELIST[$i-1]}")
+ local SPEC_DST_FILE=$(target_file "${FILELIST[$i-1]}")
+ local SPEC_ARGS=$(target_args "${FILELIST[$i-1]}")
+ local OUTPUT_DIR=
+ local TMP_DIR=
+ local SRC_FILE=
+ local DST_FILE=
+ local IS_PRODUCT_PACKAGE=false
+
+ # Note: this relies on the fact that the ${FILELIST[@]} array
+ # contains first ${PRODUCT_COPY_FILES_LIST[@]}, then ${PRODUCT_PACKAGES_LIST[@]}.
+ if [ "${i}" -gt "${PRODUCT_COPY_FILES_COUNT}" ]; then
+ IS_PRODUCT_PACKAGE=true
+ fi
+
+ if [ "${SPEC_ARGS}" = "rootfs" ]; then
+ OUTPUT_DIR="${OUTPUT_ROOT}/rootfs"
+ TMP_DIR="${OUTPUT_TMP}/rootfs"
+ else
+ OUTPUT_DIR="${OUTPUT_ROOT}"
+ TMP_DIR="${OUTPUT_TMP}"
+ fi
+ SRC_FILE="${SPEC_SRC_FILE}"
+ DST_FILE="${SPEC_DST_FILE}"
+
+ local VENDOR_REPO_FILE="$OUTPUT_DIR/${DST_FILE}"
+ local BLOB_DISPLAY_NAME="${DST_FILE}"
+ mkdir -p $(dirname "${VENDOR_REPO_FILE}")
+
+ # Check pinned files
+ local HASH="$(echo ${HASHLIST[$i-1]} | awk '{ print tolower($0); }')"
+ local FIXUP_HASH="$(echo ${FIXUP_HASHLIST[$i-1]} | awk '{ print tolower($0); }')"
+ local KEEP=""
+ if [ "$DISABLE_PINNING" != "1" ] && [ "$HASH" != "x" ]; then
+ if [ -f "${VENDOR_REPO_FILE}" ]; then
+ local PINNED="${VENDOR_REPO_FILE}"
+ else
+ local PINNED="${TMP_DIR}${DST_FILE}"
+ fi
+ if [ -f "$PINNED" ]; then
+ local TMP_HASH=$(get_hash "${PINNED}")
+ if [ "${TMP_HASH}" = "${HASH}" ] || [ "${TMP_HASH}" = "${FIXUP_HASH}" ]; then
+ KEEP="1"
+ if [ ! -f "${VENDOR_REPO_FILE}" ]; then
+ cp -p "$PINNED" "${VENDOR_REPO_FILE}"
+ fi
+ fi
+ fi
+ fi
+
+ if [ "${KANG}" = false ]; then
+ printf ' - %s\n' "${BLOB_DISPLAY_NAME}"
+ fi
+
+ if [ "$KEEP" = "1" ]; then
+ printf ' + keeping pinned file with hash %s\n' "${HASH}"
+ else
+ FOUND=false
+ PARTITION_SOURCE_DIR=
+ # Try Lineage target first.
+ for CANDIDATE in "${DST_FILE}" "${SRC_FILE}"; do
+ PARTITION=$(echo "$CANDIDATE" | cut -d/ -f1)
+ if [ "$PARTITION" = "system" ]; then
+ PARTITION_SOURCE_DIR="$SYSTEM_SRC"
+ elif [ "$PARTITION" = "vendor" ]; then
+ PARTITION_SOURCE_DIR="$VENDOR_SRC"
+ elif [ "$PARTITION" = "product" ]; then
+ PARTITION_SOURCE_DIR="$PRODUCT_SRC"
+ elif [ "$PARTITION" = "odm" ]; then
+ PARTITION_SOURCE_DIR="$ODM_SRC"
+ fi
+ CANDIDATE_RELATIVE_NAME=$(echo "$CANDIDATE" | cut -d/ -f2-)
+ get_file ${CANDIDATE_RELATIVE_NAME} ${VENDOR_REPO_FILE} ${PARTITION_SOURCE_DIR} && {
+ FOUND=true
+ break
+ }
+ # Search with the full system/ prefix if the file was not found on the system partition
+ # because we may be searching in a mounted system-as-root system.img
+ if [[ "${FOUND}" = false && "$PARTITION" = "system" ]]; then
+ get_file ${CANDIDATE} ${VENDOR_REPO_FILE} ${PARTITION_SOURCE_DIR} && {
+ FOUND=true
+ break
+ }
+ fi
+ done
+
+ if [ -z "${PARTITION_SOURCE_DIR}" ]; then
+ echo "$CANDIDATE has no preceeding partition path. Prepend system/, vendor/, product/, or odm/ to this entry."
+ fi
+
+ if [ "${FOUND}" = false ]; then
+ printf ' !! %s: file not found in source\n' "${BLOB_DISPLAY_NAME}"
+ continue
+ fi
+ fi
+
+ # Blob fixup pipeline has 2 parts: one that is fixed and
+ # one that is user-configurable
+ local PRE_FIXUP_HASH=$(get_hash ${VENDOR_REPO_FILE})
+ # Deodex apk|jar if that's the case
+ if [[ "$FULLY_DEODEXED" -ne "1" && "${VENDOR_REPO_FILE}" =~ .(apk|jar)$ ]]; then
+ oat2dex "${VENDOR_REPO_FILE}" "${SRC_FILE}" "${SYSTEM_SRC}"
+ if [ -f "$TMPDIR/classes.dex" ]; then
+ zip -gjq "${VENDOR_REPO_FILE}" "$TMPDIR/classes"*
+ rm "$TMPDIR/classes"*
+ printf ' (updated %s from odex files)\n' "${SRC_FILE}"
+ fi
+ elif [[ "${VENDOR_REPO_FILE}" =~ .xml$ ]]; then
+ fix_xml "${VENDOR_REPO_FILE}"
+ fi
+ # Now run user-supplied fixup function
+ blob_fixup "${BLOB_DISPLAY_NAME}" "${VENDOR_REPO_FILE}"
+ local POST_FIXUP_HASH=$(get_hash ${VENDOR_REPO_FILE})
+
+ if [ -f "${VENDOR_REPO_FILE}" ]; then
+ local DIR=$(dirname "${VENDOR_REPO_FILE}")
+ local TYPE="${DIR##*/}"
+ if [ "$TYPE" = "bin" -o "$TYPE" = "sbin" ]; then
+ chmod 755 "${VENDOR_REPO_FILE}"
+ else
+ chmod 644 "${VENDOR_REPO_FILE}"
+ fi
+ fi
+
+ if [ "${KANG}" = true ]; then
+ print_spec "${IS_PRODUCT_PACKAGE}" "${SPEC_SRC_FILE}" "${SPEC_DST_FILE}" "${SPEC_ARGS}" "${PRE_FIXUP_HASH}" "${POST_FIXUP_HASH}"
+ fi
+
+ # Check and print whether the fixup pipeline actually did anything.
+ # This isn't done right after the fixup pipeline because we want this print
+ # to come after print_spec above, when in kang mode.
+ if [ "${PRE_FIXUP_HASH}" != "${POST_FIXUP_HASH}" ]; then
+ printf " + Fixed up %s\n" "${BLOB_DISPLAY_NAME}"
+ # Now sanity-check the spec for this blob.
+ if [ "${KANG}" = false ] && [ "${FIXUP_HASH}" = "x" ] && [ "${HASH}" != "x" ]; then
+ printf "WARNING: The %s file was fixed up, but it is pinned.\n" ${BLOB_DISPLAY_NAME}
+ printf "This is a mistake and you want to either remove the hash completely, or add an extra one.\n"
+ fi
+ fi
+
+ done
+
+ # Don't allow failing
+ set -e
+}
+
+#
# extract_firmware:
#
# $1: file containing the list of items to extract