Guest User

update script

a guest
Sep 10th, 2020
244
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/bin/bash
  2.  
  3. #
  4. # perform a system update, given a new rootfs.tar[.gz] file
  5. #
  6. if [ -s /etc/sysupdate.conf ]; then
  7.         . /etc/sysupdate.conf
  8. else
  9.         server=api.aether.net
  10.         PKG_CACHE=/var/music/data/update
  11.         PKG_MOUNT=/var/music/data/update/mnt
  12.         PART_MOUNT=/mnt
  13.         MCA_CERT_DIR=/etc/ssl/certs/aether
  14.         CA_BUNDLE_AETHER_SERVERS=/etc/ssl/certs/aether-servers-ca-bundle.crt
  15.         CA_BUNDLE_DOWNLOAD=/etc/ssl/certs/ca-bundle.crt
  16.         cert_temp=
  17.         LOCK_FILE=/var/run/sysupdate.pid
  18.         INSIDE_FILE=rootfs.tar.gz
  19.         status_file=
  20.         DATABASE=/var/tuned/sysupdated.db
  21. fi
  22.  
  23. config() {
  24.         mp-config --config=/etc/tuned/tuned.conf --override get ${@+"$@"}
  25. }
  26.  
  27. # Exits the script with a defined return status and, optionally,
  28. # writes a string of text into the status file if both the text
  29. # and status file are specified.
  30. function exit_status()
  31. {
  32.     if [ "${status_file}" != "" ]; then
  33.         echo "$2" > ${status_file}
  34.     fi
  35.         if [ -f $DATABASE ]; then
  36.                 echo "INSERT INTO update_state(result) VALUES ('$2');" | sqlite3 ${DATABASE}
  37.         fi
  38.     if grep -q ${PKG_MOUNT} /proc/mounts
  39.     then
  40.         fusermount -u ${PKG_MOUNT}
  41.     fi
  42.     echo "Terminating sysupdate with status $1 due to $2"
  43.     exit $1
  44. }
  45.  
  46. function clean()
  47. {
  48.     echo "Cleaning up ..."
  49.     if grep -q ${PKG_MOUNT} /proc/mounts
  50.     then
  51.         fusermount -u ${PKG_MOUNT}
  52.     fi
  53.     while [ -d ${PKG_MOUNT} ]; do
  54.         echo "Waiting for metfs to finish unmounting"
  55.         sleep 1
  56.         rmdir ${PKG_MOUNT}
  57.     done
  58.     rm -f ${cert_temp}
  59.     rm -f ${pubkey_temp}
  60.     if [ -n "${update_complete}" -o -n "${invalid_image}" ]; then
  61.         if [ -n "${download_url}" ] && [ -f "${update_image}" ]; then
  62.             echo "Removing downloaded update file. ${update_image}"
  63.             rm -f "${update_image}"
  64.         fi
  65.     fi
  66.  
  67.     rm -f ${LOCK_FILE}
  68.     if [ -n "${need_reboot}" ]; then
  69.         echo "Reboot needed to update to $new_version"
  70.         sync
  71.         sleep 15
  72.         sync
  73.         exit_status 0 "Applied $new_version"
  74.     fi
  75. }
  76.  
  77. function download()
  78. {
  79.     current_version=${1}
  80.     alt_version=${2}
  81.     factory_version=${3}
  82.     # Check that these configuration files are present, as well
  83.     if [ ! -f /etc/tuned/tuned.conf ]; then
  84.         echo "Error: Configuration file /etc/tuned/tuned.conf does not exist"
  85.         exit_status 1 "Configuration"
  86.     fi
  87.     if [ ! -f /var/etc/.certs/device_id ]; then
  88.         echo "Error: Device ID does not exist"
  89.         exit_status 1 "Configuration"
  90.     fi
  91.         if [ -f /var/root/.sysupdate_exempt -a "${force}" -ne "1" ]; then
  92.                 echo "Not attempting to download: device is exempt from updates"
  93.                 exit_status 1 "Exempt"
  94.         fi
  95.  
  96.     if [ "x${current_version}" == "x" -o "x${alt_version}" == "x" ]; then
  97.         echo "Error: current [${current_version}] and alt [${alt_version}] versions need to be supplied, were not"
  98.         exit_status 1 "Configuration"
  99.     fi
  100.     # Do a quick sanity check of the date to ensure the clock is set to a somewhat reasonable value (the MCU epoch time is 2000)
  101.     # This is necessary for certificate validation
  102.     year=$(date -I | cut -c1-4)
  103.     if [ ${year} -lt 2014 ]; then
  104.         echo "Please check the system clock, it seems to be set incorrectly.  We think the year is ${year}."
  105.         exit_status 1 "Date"
  106.     fi
  107.  
  108.     cert_file=$(config main.cert-file)
  109.     cert_pass=$(config main.cert-password)
  110.     cert_temp=$(mktemp -q -t cert.XXXXXX)
  111.     device_id=$(cat /var/etc/.certs/device_id)
  112.     # Prior to invoking openssl, check that the certificate file is present
  113.     if [ ! -f ${cert_file} ]; then
  114.         echo "Error: Certificate file ${cert_file} does not exist!"
  115.         exit_status 1 "Configuration"
  116.     fi
  117.     openssl pkcs12 -in ${cert_file} -passin pass:${cert_pass} -nomacver -nodes -out "${cert_temp}"
  118.     url="https://${update_server}/services/2012.257/devices/${device_id}/firmware?current_version=${current_version}&force=${force}&alt_version=${alt_version}&factory_version=${factory_version}"
  119.     echo "Querying server to see if update is available: ${url}"
  120.     # A large connect timeout is needed to allow for ipv6/ipv4/multiple DNS servers to timeout and work. TUNE-3796
  121.     download_url=$(curl -s -S -f --connect-timeout 25 --max-time 300 --cert "${cert_temp}" --cacert "${CA_BUNDLE_AETHER_SERVERS}" "${url}")
  122.     res=$?
  123.     if [ $res -ne 0 ]; then
  124.         echo "Error: ${download_url} failed with ${res}"
  125.         exit_status $res "Network"
  126.     fi
  127.     if [ -z "$download_url" ]; then
  128.         echo "No update available"
  129.         exit_status 0 "No Update"
  130.     fi
  131.     echo "Update available at: ${download_url}"
  132.     file_name=$(basename "${download_url}")
  133.     mkdir -p "${PKG_CACHE}"
  134.         #
  135.         # ensure that there is sufficient space in $PKG_CACHE
  136.         #
  137.         free_blocks=$(df -P "${PKG_CACHE}" | sed -n 2p | awk '{print $4}')
  138.         if [ "${free_blocks}" -lt 100000 ]; then
  139.                 echo "Insufficient space in $PKG_CACHE, using /tmp instead"
  140.                 PKG_CACHE=/tmp
  141.         fi
  142.     update_image="${PKG_CACHE}/${file_name}"
  143.  
  144.     pushd "${PKG_CACHE}"
  145.  
  146.     # If the filename exists, then it has been fully downloaded.
  147.     if [ ! -f ${file_name} ]; then
  148.         # A large connect timeout is needed to allow for ipv6/ipv4/multiple DNS servers to timeout and work. TUNE-3796
  149.         curl --connect-timeout 25 --max-time 172800 -C - --cacert "${CA_BUNDLE_DOWNLOAD}" -o "${file_name}.part" "${download_url}"
  150.         res=$?
  151.         if [ $res -ne 0 ]; then
  152.             popd
  153.             echo "Error: Download failure. ${res}"
  154.             exit_status $res "Network"
  155.         fi
  156.         mv "${file_name}.part" "${file_name}"
  157.     else
  158.         echo "'${file_name}' already fully downloaded."
  159.     fi
  160.  
  161.     popd
  162.     echo "${update_image}"
  163. }
  164.  
  165. function check_version()
  166. {
  167.         if [ -f /proc/aether/devtype ]; then
  168.                 case $(cat /proc/aether/devtype) in
  169.                 (tiburon)       firmware=FRM000104 ;;
  170.                 (salinas*)      firmware=FRM000105 ;;
  171.                 (*)             firmware=FRMxxxxxx ;;
  172.                 esac
  173.         else
  174.                 firmware=$(echo $BUILD_VERSION | awk -F. '{print $1}')
  175.         fi
  176.         version=$(echo "${1}" | awk -F. '{print $1'})
  177.         [ "$version" = "$firmware" ]
  178.         return $?
  179. }
  180.  
  181. function bad_update()
  182. {
  183.     printf "%s does not appear to be a valid update file: %s\n" "${1}" "${2}" 1>&2
  184.         # categorize this as a network error ... sysupdated will then try to redownload soon
  185.         # if it was downloaded, remove the broken package
  186.         if [ -n "${update_server}" ]; then
  187.                 invalid_image=true
  188.         fi
  189.     exit_status 1 "Network"
  190. }
  191.  
  192. function verify_package()
  193. {
  194.     # Verifying a package is a four step process
  195.  
  196.     # 0. Mount the package
  197.     mkdir -p ${PKG_MOUNT}
  198.     export METFS_PASSPHRASE='GyamY!ASDb5asBZ$Faf5(24qBAhasfg'
  199.     # Not entirely portable...debian (and BusyBox) uses realpath, other distros use readlink
  200.     metfs --mount ${PKG_MOUNT} --file "$(realpath ${update_image})" -r
  201.     unset METFS_PASSPHRASE
  202.  
  203.     # 1. Make sure the inside file exists.
  204.     if [ ! -r $PKG_MOUNT/$INSIDE_FILE ]; then
  205.         bad_update ${update_image} "Mising $INSIDE_FILE in the interior of the update file"
  206.     fi
  207.  
  208.     sign_cert="$PKG_MOUNT/cert.pem"
  209.  
  210.     # 2. Verify the signature inside the package comes from the cert in the package. Do not change the file names here
  211.     pubkey_temp=$(mktemp -q -t pubkey.XXXXXX)
  212.     openssl x509 -pubkey -noout -in "${sign_cert}" > ${pubkey_temp}
  213.     cat "$PKG_MOUNT/rootfs.tar.gz" "$PKG_MOUNT/version.txt" "$PKG_MOUNT/pre-inst.sh" "$PKG_MOUNT/post-inst.sh" "$PKG_MOUNT/bootloader.img" "$PKG_MOUNT/bootloader.ver" | \
  214.         openssl dgst -sha256 -verify "${pubkey_temp}" -signature "$PKG_MOUNT/signature.sha256"
  215.     if [ $? -ne 0 ]; then
  216.         bad_update ${update_image} "Package signature is not valid"
  217.     fi
  218.         # 2a. Verify the version inside the package matches the current one
  219.         if ! check_version $(cat "$PKG_MOUNT/version.txt"); then
  220.                 bad_update ${update_image} "Version mismatch: this firmware cannot be loaded on this device"
  221.         fi
  222.  
  223.     # 3. Verify the cert can be used for Code signing. This will lock out using a device cert
  224.     openssl x509 -in "${sign_cert}" -noout -text -certopt no_serial,no_sigdump,no_issuer,no_subject,no_header,no_version,no_signame,no_validity,no_pubkey,no_aux | egrep -A1 '^  *X509v3 Extended Key Usage: critical$' | egrep -o '^  *Code Signing,'
  225.     if [ $? -ne 0 ]; then
  226.         bad_update ${update_image} "Certificate used to sign package does support code signing"
  227.     fi
  228.  
  229.     # Check if we are in direct package mode and if so skip the verify to root chain so a developer build can be installed
  230.  
  231.     # 4. Verify the cert is properly signed by our root anchor only. This will
  232.     # Openssl verify doesn't set its return code to non 0, so we have to use the contents of its output.
  233.     # If everything passed, just "OK" wihtout quotes is returned. If anything failed, then more is returned
  234.     # This check also makes sure the purpose is valid, but smimesign is not the best one, but only one we can
  235.     # use with the verify command. We will check the extended purpose fields in a seperate call
  236.     if [ -z "${no_cert_chain_verify}" ]
  237.     then
  238.         openssl verify -CAfile "${MCA_CERT_DIR}/aether_root.pem" "${sign_cert}"
  239.         if [ $? -ne 0 ]; then
  240.             bad_update ${update_image} "Certificate does not validate to a trusted root"
  241.         fi
  242.     fi
  243.  
  244.     return 0
  245. }
  246.  
  247. function clean_part()
  248. {
  249.     if [[ "${verbose}" ]]
  250.     then
  251.         printf "Erasing %s. Continue? " ${1}
  252.         read yorn
  253.         case $yorn in
  254.         ([yY]*) : nothing
  255.             ;;
  256.         (*)
  257.             printf "Aborting\n"
  258.             exit_status 42 "User Abort"
  259.             ;;
  260.         esac
  261.     fi
  262.     mkfs.ext4 ${1} -L rootfsf${2}
  263. }
  264.  
  265. function find_next_dev()
  266. {
  267.     cur_root_dev=${1}
  268.     next_part=${2}
  269.     case $next_part in
  270.     (f) partition=1
  271.         ;;
  272.     (a) partition=2
  273.         ;;
  274.     (b) partition=3
  275.         ;;
  276.     esac
  277.     printf "%s" $cur_root_dev | sed -e 's/.$/'$partition'/'
  278. }
  279.  
  280. function get_partition_and_dev()
  281. {
  282.         factory=${1-0}
  283.     part_id=$(sed -e 's/.* partition=\([abf]\).*/\1/' < /proc/cmdline)
  284.     dev=$(sed -e 's/.* root=\([^ ]*\).*/\1/' < /proc/cmdline)
  285.     case $part_id in
  286.     (f) next_part=a
  287.         ;;
  288.     (a) next_part=b
  289.         ;;
  290.     (b) next_part=a
  291.         ;;
  292.     (*) printf "Current root partition could not be parsed from %s\n" $part_id 1>&2
  293.         exit_status 2 "Configuration"
  294.         ;;
  295.     esac
  296.         if [[ "${factory}" = 1 ]]
  297.         then
  298.                 next_part=f
  299.         fi
  300.     next_dev=$(find_next_dev $dev $next_part)
  301.         if [[ "${part_id}" = "${next_part}" ]]
  302.         then
  303.                 printf "Cannot overwrite current partition (%s)\n" ${part_id} 1>&2
  304.                 exit_status 2 "Configuration"
  305.         fi
  306.     if [[ "${verbose}" ]]
  307.     then
  308.         printf "Updating from partion %s on %s to partition %s on %s\n" $part_id $dev $next_part $next_dev 1>&2
  309.     fi
  310.     printf "%s %s" $next_dev $next_part
  311. }
  312.  
  313. function update_bootloader()
  314. {
  315.     if [ -e /proc/cmdline -a -e ${PKG_MOUNT}/bootloader.ver -a -e ${PKG_MOUNT}/bootloader.img ]; then
  316.         uboot_cur_ver=$(sed -e 's/.* uboot_ver="\([^"]*\).*/\1/' < /proc/cmdline)
  317.         uboot_dev=$(sed -e 's/.* uboot_dev=\([^ ]*\).*/\1/' < /proc/cmdline)
  318.  
  319.         uboot_new_ver=$(< ${PKG_MOUNT}/bootloader.ver)
  320.         if [ "${uboot_cur_ver}" = "${uboot_new_ver}" ]; then
  321.             echo "Bootloader versions match, not upgrading."
  322.             return 0
  323.         fi
  324.         echo "Bootloader needs to be updated to '${uboot_new_ver}' on device '${uboot_dev}'"
  325.         dd if=${PKG_MOUNT}/bootloader.img of=${uboot_dev} bs=512 conv=notrunc seek=2
  326.     else
  327.         echo "Couldn't determine if bootloader needs to be updated"
  328.         return 1
  329.     fi
  330. }
  331.  
  332. function get_current_version()
  333. {
  334.     grep BUILD_VERSION /etc/os-release | awk -F= '{print $2}'
  335. }
  336.  
  337. function get_alt_version()
  338. {
  339.     dev=${1}
  340.     # 99% of the time, we'll run this script and not actually update the system.  However, everytime we request
  341.     # an update and get the alternate version, we mount the alternate partition, which causes this kernel message
  342.     # to be printed to the console:
  343.     #    EXT4-fs (mmcblk0p3): mounted filesystem with ordered data mode. Opts: (null)
  344.     # Here we temporarily disable kernel printk()s in order to suppress that spam.
  345.     old=$(cat /proc/sys/kernel/printk)
  346.     echo "4 1 1 7" > /proc/sys/kernel/printk
  347.     mount -t ext4 -oro $dev ${PART_MOUNT}
  348.         set -o pipefail
  349.     grep BUILD_VERSION ${PART_MOUNT}/etc/os-release | awk -F= '{print $2}' || echo unknown
  350.         set +o pipefail
  351.     umount ${PART_MOUNT}
  352.     echo ${old} > /proc/sys/kernel/printk
  353. }
  354.  
  355. function is_official_build()
  356. {
  357.     # Expected path to /etc/os-release
  358.     osFile=${1}
  359.     # rawVersion will be something like
  360.     # FRM000102.00.02.20131203182305-npelis  <-- developer build
  361.     # FRM000102.01.01.0207                   <-- official build
  362.     # According to Aron, official builds shall always be padded four digit numbers
  363.     # while developer builds shall always be date/time stamps + usernames.  So this
  364.     # is how we differentiate between official vs developer builds
  365.     rawVersion=$(grep BUILD_VERSION ${osFile} | sed 's/BUILD_VERSION=//')
  366.     buildNum=$(echo ${rawVersion} | sed 's/.*\.\(.*\)$/\1/')
  367.     if [ ${#buildNum} -eq 0 ]; then
  368.         echo -1
  369.     elif [ ${#buildNum} -eq 4 ]; then
  370.         echo 1
  371.     else
  372.         echo 0
  373.     fi
  374. }
  375.  
  376. function falsify_build()
  377. {
  378.     # rawVersion will be something like
  379.     # FRM000102.00.02.20131203182305-npelis                  <-- developer private build
  380.     # FRM000102.01.01.0207                   <-- developer public build
  381.     # FRM000102.01.02.0207                   <-- official build
  382.         # NOTE falsified build numbers pass the "is_official_build" test
  383.     rawVersion=${1}
  384.     # Expected path to /etc/os-release
  385.     #osFile=${1}
  386.     #rawVersion=$(grep BUILD_VERSION ${osFile} | sed 's/BUILD_VERSION=//')
  387.     newVersion=$(echo ${rawVersion} | awk -F. '{ printf "%s.00.00.0000\n", $1}')
  388.     echo ${newVersion}
  389. }
  390.  
  391. function usage()
  392. {
  393.     printf "%s [-d|--download] [-n|--no-cert-chain-verify] [-o|--overwrite-factory] [-f|--force] [-p package_file] [-s update_server] [-v|--verbose[=level]] [-t status_file]\n" ${0} 1>&2
  394.     printf "  Note: -p (or --pkg) and -s (or --server) are mutually exclusive\n" 1>&2
  395.     printf "  Note: -d (or --download) Will just download the update file, but not install it\n" 1>&2
  396.     printf "  status_file causes the result of the operation to be written to the specified file\n" 1>&2
  397.     exit_status 1 "Usage"
  398. }
  399.  
  400. function main()
  401. {
  402.     OPTIONS=$(getopt -o dfnot:p:s:v::h --long download,no-cert-chain-verify,status_file:,force,pkg:,server:,verbose::,help -n ${0} -- ${@+"$@"})
  403.     if [ $? != 0 ] ; then printf "Bad options" >&2 ; exit_status 1 "Usage"; fi
  404.     force=0
  405.         factory=0
  406.     download_only=0
  407.     update_server="${server}"
  408.         program=$(basename $0)
  409.     eval set -- "$OPTIONS"
  410.     while true ; do
  411.         case "$1" in
  412.         (-d|--download)
  413.             download_only=1
  414.             shift
  415.             ;;
  416.         (-f|--force)
  417.             force=1
  418.             shift
  419.             ;;
  420.         (-n|--no-cert-chain-verify)
  421.                         case "$program" in
  422.                         (sysupdate|sysupdate.sh)
  423.                                 no_cert_chain_verify=true
  424.                                 ;;
  425.                         (*)
  426.                                 printf "Permission denied\n" 1>&2
  427.                                 exit_status 1 "Usage"
  428.                                 ;;
  429.                         esac
  430.             shift
  431.             ;;
  432.                 (-o|--overwrite-factory)
  433.                         factory=1
  434.                         shift
  435.                         ;;
  436.         (-p|--pkg)
  437.             update_image=$2
  438.             update_server=
  439.             shift 2
  440.             ;;
  441.         (-s|--server)
  442.             update_server=$2
  443.             update_image=
  444.             shift 2
  445.             ;;
  446.         (-v|--verbose)
  447.             case "${2}" in
  448.             ([0-9]*)
  449.                 verbose=$2
  450.                 ;;
  451.             (*)
  452.                 verbose=$((verbose+1))
  453.                 ;;
  454.             esac
  455.             shift 2;;
  456.         (-t|--status_file)
  457.             status_file=$2
  458.             shift 2
  459.             ;;
  460.         (-h|--help)
  461.             usage
  462.             shift ;;
  463.         (--)    shift
  464.             break ;;
  465.         (*) echo -- "'$1' unknown argument"
  466.             usage
  467.             exit_status 1 "Usage"
  468.         esac
  469.     done
  470.  
  471.     if [[ $EUID -ne 0 ]]; then
  472.         echo "You must be root to run this script"
  473.         exit_status 1 "Root_fail"
  474.     fi
  475.  
  476.     if [ -s "${update_image}" -a -s "${update_server}" ]
  477.     then
  478.         echo -- "--pkg and --server are mutually exclusive" 1>&2
  479.         usage
  480.         exit_status 1 "Usage"
  481.     fi
  482.     # Check for a set, but nonexistent package update file.  Bail out.
  483.     if [ "x${update_image}" != "x" -a ! -e "${update_image}" ]
  484.     then
  485.         echo "Error: The package file ${update_image} does not exist." 1>&2
  486.         exit_status 1 "Usage"
  487.     fi
  488.     set -- $(get_partition_and_dev $factory)
  489.     next_dev=$1
  490.     next_part=$2
  491.     alt_version=$(get_alt_version ${next_dev})
  492.     current_version=$(get_current_version)
  493.     official_build=$(is_official_build /etc/os-release)
  494.  
  495.     factory_dev=$(find_next_dev $(sed -e 's/.* root=\([^ ]*\).*/\1/' < /proc/cmdline) f)
  496.     factory_version=$(get_alt_version ${factory_dev})
  497.  
  498.     if [ ${force} -eq 1 ]; then
  499.         new_alt_version=$(falsify_build ${alt_version})
  500.         new_current_version=$(falsify_build ${current_version})
  501.         echo "Info: Falsifying build numbers.  Actual builds on current/alternate partitions are ${current_version}/${alt_version}."
  502.         echo "Info: Falsified builds are ${new_current_version}/${new_alt_version}"
  503.         current_version=${new_current_version}
  504.         alt_version=${new_alt_version}
  505.                 official_build=1
  506.     fi
  507.  
  508.         # if the current build is not an official one, only proceed if this is
  509.         # either forced (-f) or from a package (-p),
  510.  
  511.     if [ -z "${update_image}" ]; then
  512.                 if [ ${official_build} -eq 1 ]; then
  513.                         download ${current_version} ${alt_version} ${factory_version}
  514.                 else
  515.                         echo "Error: current build is not official. Can only update with -f" 1>&2
  516.                         exit_status 1 "Usage"
  517.                 fi
  518.     fi
  519.  
  520.     if [ ${download_only} -eq 1 ]; then
  521.         echo "Download of update finished"
  522.         exit_status 0 "Download Only"
  523.     fi
  524.  
  525.         if ! batt --ac > /dev/null
  526.         then
  527.                 # check that the system has as least 10% battery life before proceeding,
  528.                 # unless forced through with the -f flag
  529.                 level=$(batt -m 10)
  530.                 if [ $? -ne 0 -a ${force} -ne 1 ]; then
  531.                         printf "Battery must be connected, and must be at minimum 10%% charge to continue (actually at %s)\n" ${level} 1>&2
  532.                         exit_status 1 "Battery"
  533.                 fi
  534.         fi
  535.     # update_image should now be set
  536.     if verify_package $update_image
  537.     then
  538.         $PKG_MOUNT/pre-inst.sh
  539.         case $? in
  540.         (0)
  541.             clean_part $next_dev $next_part
  542.             sync; sync;
  543.             mount -t ext4 $next_dev ${PART_MOUNT}
  544.             ;;
  545.         (1)
  546.             mount -t ext4 $next_dev ${PART_MOUNT}
  547.             ;;
  548.         (*)
  549.             printf "pre-inst.sh: failed\n" 1>&2
  550.             exit_status 1 "Install"
  551.             ;;
  552.         esac
  553.         [ "${verbose-0}" -gt 0 ] && vflag=v
  554.         tar="gunzip -c $PKG_MOUNT/rootfs.tar.gz | tar x${vflag}f -"
  555.         echo ${tar}
  556.         (set -e;cd ${PART_MOUNT} && eval ${tar})
  557.         if [ $? -ne 0 ]; then
  558.             printf "Failed to untar contents of package, aborting system update\n" 1>&2
  559.             exit_status 1 "Install"
  560.         fi
  561.         update_bootloader
  562.         $PKG_MOUNT/post-inst.sh
  563.                 new_version=$(eval $(grep BUILD_VERSION $PART_MOUNT/etc/os-release);echo $BUILD_VERSION)
  564.         sync
  565.         umount ${PART_MOUNT}
  566.  
  567.         update_complete="y"
  568.         echo "Sync'ing to disk"
  569.         sync
  570.         echo "Setting MCU flags to switch to partition '$next_part' at the next boot"
  571.         if bootflags -s -p $next_part -f 0
  572.         then
  573.             need_reboot=1
  574.         else
  575.             printf "Update installed, but unable to access mcu\n" 1>&2
  576.             exit_status 42 "MCU"
  577.         fi
  578.     fi
  579. }
  580.  
  581. # Create a pid file
  582. if [ -f ${LOCK_FILE} ]; then
  583.         otherpid=$(cat ${LOCK_FILE})
  584.         if [ -n "${otherpid}" ] && grep -q "sysupdate" /proc/${otherpid}/cmdline; then
  585.                 echo "System Update already running, quitting this copy"
  586.                 exit_status 1 "Duplicate"
  587.         else
  588.                 echo "Removing stale lock file ${LOCK_FILE}"
  589.                 # do not use -f ... if the lock file is owned by someone else, this shold fail
  590.                 rm ${LOCK_FILE} || exit_status 1 "PIDFail"
  591.         fi
  592. fi
  593. echo "$$" > ${LOCK_FILE} || exit_status 1 "PIDFail"
  594.  
  595. trap clean EXIT HUP INT QUIT TERM
  596.  
  597. main ${@+"$@"}
  598.  
  599.  
RAW Paste Data