#!/bin/bash # Copyright 2016-2020 Jay Flood, SP, Brasil # All rights reserved. # # Redistribution and use of this script, with or without modification, is # permitted provided that the following conditions are met: # # 1. Redistributions of this script must retain the above copyright # notice, this list of conditions and the following disclaimer. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Author: brokenman@porteus.org # # This is a script to update Porteus # Source functions . /usr/share/porteus/porteus-functions get_colors # Set variables SERVER=`awk -F= '/SERVER=/{print$NF}' /etc/porteus.conf` PVER=`cat /etc/porteus-version` CF=/etc/porteus TMPDIR=/tmp/.updport.$$ case `uname -m` in x86_64) ARCH=x86_64; LIBSUFFIX=64 ;; i?86) ARCH=i586; LIBSUFFIX="" ;; esac SERVER=$SERVER/$ARCH/$PVER # Check for debug option if [ `echo $* | grep -o verbose` ]; then bose=0 log=/var/log/porteus-update.log fi sayupdate(){ echo "[${txtbold}${txtcyan}UPDATE$rst] $1"; } sayok(){ echo "[${txtbold}${txtgreen}OK$rst] $1"; } saydowngrade(){ echo "[${txtbold}${txtred}DOWNGRADE$rst] $1"; } cleanup(){ [ $bose ] && cyan "Cleaning up ..." rm -rf $TMPDIR 2>/dev/null [ -e /tmp/.list ] && rm /tmp/.list [ $bose ] && cyan "Task finished!" exit } trap cleanup SIGHUP SIGINT SIGTERM get_target_base(){ echo echo "The base modules go in your base directory. Unfortunately I am not" echo "able to write to the destination. You can choose an alternative" echo "location to download your base module updates to." echo echo "Enter a target directory to download to: " read -ep "> " answ # Check that this place is a directory and is writable if [ ! -d $answ ]; then red "No directory exists at $answ" unset answ $FUNCNAME elif [ ! -w $answ ]; then red "$answ is not writable" unset answ $FUNCNAME else echo bold "Modules will be downloaded to $answ" fi TARG=$answ && unset answ } get_fastest_mirror(){ ## get mirror list MIRRORS=$(curl -s http://porteus.org/porteus-mirrors.txt) CNT=`echo $MIRRORS | wc -w` ## Number of seconds before the test is considered a failure TIMEOUT="4" ## Store results in an array RESULTS="" echo "Checking fastest mirror ..." for MIRROR in $MIRRORS ; do echo -n "Processing link speed: " echo -ne "$CNT"\\r " " let CNT=$(( CNT - 1 )) URL="${MIRROR}" TIME=`curl --max-time $TIMEOUT --silent --output /dev/null --write-out %{time_total} $URL` if [ "$TIME" == "0.000" ] ; then echo "Fail"; else #echo $TIME RESULTS="${RESULTS}${TIME}\t${MIRROR}\n"; fi done; echo -e "\nResults:" echo -e $RESULTS | sort -n > /tmp/.list sed -i '/^$/d' /tmp/.list fm=`head -n1 /tmp/.list | awk '{print$NF}'` cat /tmp/.list } array_menu(){ echo echo "$1" echo "$2" && echo select CHOICE in ${RESULT[@]}; do if [ -z "$CHOICE" ]; then bold "User aborted." && echo cleanup else bold "$CHOICE locale chosen" fi break done } menu_multiple_choice() { echo green "All available updates are selected:" echo for i in ${!required[@]}; do printf "%3d%s) %s\n" $((i+1)) "${choices[i]:- }" "${required[i]}" done [[ "$msg" ]] && echo "$msg"; : } menu_deselect(){ required=( $@ ) clear choices=( `printf '+ %.0s' {1..100}` ) prompt="`gettext "Deselect an item (again to reselect, ENTER when ready):"`" while menu_multiple_choice && read -n1 -rp "$prompt" num && [[ "$num" ]]; do [[ "$num" != *[![:digit:]]* ]] && (( num > 0 && num <= ${#required[@]} )) || { msg="Invalid option: $num"; clear; continue } ((num--)); msg="" [[ "${choices[num]}" ]] && choices[num]="" || choices[num]="+" clear done msg=" nothing" for i in ${!required[@]}; do #[[ "${choices[i]}" = "+" ]] && { FINALPKGS="${FINALPKGS} ${required[i]}"; msg=""; } if [ $frompackageGet ]; then [[ "${choices[i]}" = "+" ]] && NEWFINAL+=( `echo $FINALPKGS|tr ' ' '\n'|grep ${required[i]}` ) elif [ $fromsystemDeps=0 ]; then [[ "${choices[i]}" = "+" ]] && NEWFINAL+=( ${required[i]} ) else echo "Error at $FUNCNAME $LINENO: please notify brokenman" fi done FINALPKGS=${NEWFINAL[@]} && unset NEWFINAL echo } # Get local versions and put into array for a in 001-core 002-xorg 002-xtra 003-xfce 003-cinnamon 003-kde 003-mate 003-lxde 003-lxqt 003-openbox 003-gnome; do if [ -e $CF/${a}.ver ]; then [ $bose ] && cyan "$a module detected" LVERS+=( "`grep $a $CF/${a}.ver`" ) fi if [[ `ls /mnt/live/memory/images/ | grep -o $a` ]]; then case $a in 003-xfce) desktop=xfce ;; 003-cinnamon) desktop=cinnamon ;; 003-kde) desktop=kde ;; 003-mate) desktop=mate ;; 003-lxde) desktop=lxde ;; 003-lxqt) desktop=lxqt ;; 003-openbox) desktop=openbox ;; 003-gnome) desktop=gnome ;; esac fi done [ $bose ] && cyan "Desktop appears to be: $desktop" # Create a temp dir [ ! -d $TMPDIR ] && mkdir -p $TMPDIR || rm -rf $TMPDIR/* # Download the updates file and doublecheck download $SERVER/updates/core/updates.txt $TMPDIR echo if [ ! -e $TMPDIR/updates.txt ]; then sayerror "Could not download updates.txt file" sayerror "$SERVER/updates/core/updates.txt" cleanup else mv $TMPDIR/updates.txt $TMPDIR/core-updates.txt [ $bose ] && cyan "updates.txt moved to $TMPDIR/core-updates.txt" fi # Go through array LVERS and see if any need updating echo "Checking base modules ..." for a in ${LVERS[@]}; do modname=${a%:*} echo [[ ! `grep $modname $TMPDIR/core-updates.txt` ]] && continue [ $bose ] && cyan "Processing $modname" localver=${a##*:} [ $bose ] && cyan "localver is:$localver" remotever=`awk -F/ '/'${a%:*}'/{print$2}' $TMPDIR/core-updates.txt | sort -V | tail -n1` [ $bose ] && cyan "remotever is:$remotever" modsize=`awk '/'${modname}'/{print$NF}' $TMPDIR/core-updates.txt` [ $bose ] && cyan "modsize is:$modsize" if [ "$remotever" ]; then # Check if the remote version is newer than the local version if [ $remotever -gt $localver ]; then UPDATES+=( $modname ) LINKS+=( $SERVER/updates/core/$remotever/${modname} ) [ $bose ] && bold "An update is required for $modname" [ $bose ] && cyan "Link: $SERVER/updates/core/$remotever/${modname}" #elif [ $remotever -eq $localver ]; then # sayok "$modname" # else #saydowngrade "$modname" fi fi done ## Get patches and put in array echo "Checking patch availability ..." PATCHSERVER="$SERVER/updates/patches/" [ $bose ] && echo "Patch server: $PATCHSERVER" wget $PATCHSERVER -P $TMPDIR >/dev/null 2>&1 if [ ! -e $TMPDIR/index.html ]; then sayerror "Could not download index.html from patchserver" cleanup else [ $bose ] && cyan "Downloaded index.html from patchserver" fi if [[ `awk -F'"' '/href=/ && /.xzm/{print$8}' $TMPDIR/index.html` ]]; then for a in `awk -F'"' '/href=/ && /.xzm/{print$8}' $TMPDIR/index.html`; do updateit=`egrep ".*$desktop.*.xzm$|.*alldesktops.*.xzm$" <<<$a` [ $updateit ] && remotelist+=( "$a" ) done fi rm $TMPDIR/index.html localist=( `ls $BASEFOLDER` ) PATCHES=() for i in "${remotelist[@]}"; do skip= for j in "${localist[@]}"; do [[ $i == $j ]] && { skip=1; break; } done [[ -n $skip ]] || PATCHES+=("$i") done ## Get all update links and put into an array if [[ ${PATCHES[@]} ]]; then echo "Creating links ..." for a in ${PATCHES[@]}; do DLOAD+=( $SERVER/updates/patches/$a ) done fi for a in ${LINKS[@]}; do DLOAD+=( $a ); done ## If no updates then give the all clear #clear if [[ -z ${DLOAD[@]} ]]; then echo green "####################################" bold "Porteus update report" echo cyan "You are up to date." echo cleanup else for a in ${DLOAD[@]}; do b=${a##*/} [ `grep "^00[1-3].*\.xzm$" <<<$b | egrep -v "alldesktops|patch|fixes"` ] && COREUPD+=( $b ) [ `egrep "alldesktops|fixes-[0-9]" <<<$b` ] && PATCHUPD+=( $b ) done fi if [[ ${COREUPD[@]} ]]; then green "#########################" bold "Available core updates" echo printf '%s\n' ${COREUPD[@]} echo fi if [[ ${PATCHUPD[@]} ]]; then green "#########################" bold "Available patch updates" echo printf '%s\n' ${PATCHUPD[@]} echo fi ## Ask user permission to continue read -p " Would you like to continue? [y/n]" -n 1 -r -s && echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then cleanup; fi echo ## Present menu for user to deselect options menu_deselect "${COREUPD[@]} ${PATCHUPD[@]}" [[ -z $FINALPKGS ]] && cleanup for a in $FINALPKGS; do FINALLINKS+=( `printf '%s\n' ${DLOAD[@]} | grep $a` ) done if [ $bose ]; then cyan "FINAL LINKS:" printf '%s\n' ${FINALLINKS[@]} fi # Check base folder for writability #if [ -z $1 ]; then # touch $BASEFOLDER/.test && { rm $BASEFOLDER/.test; WRITE=0; } || WRITE=1 #else # WRITE=$1 #fi touch $BASEFOLDER/.test && { rm $BASEFOLDER/.test; WRITE=0; } || WRITE=1 [ $bose ] && [ $WRITE -eq 0 ] && cyan "$BASEFOLDER is writable" [ $bose ] && [ $WRITE -eq 1 ] && cyan "$BASEFOLDER is NOT writable" # If base directory is not writable then ask for target UPDF=$BASEDIR/porteus/updates if [ "$WRITE" != 0 ]; then get_target_base else # Create the updates folder echo [ $bose ] && cyan "Creating updates folder at: $UPDF" mkdir -p $UPDF # Check that it is there if [ ! -d $UPDFs ]; then sayerror "Could not create $UPDF" cleanup fi sayok "Created updates folder" TARG=$UPDF fi ## Download updates for a in ${FINALLINKS[@]}; do [ $bose ] && "Downloading ${a##*/}" download $a $TARG # Check md5sum fil=${a##*/} if [[ `grep $fil $TMPDIR/core-updates.txt` ]]; then rmd5=`awk '/'$fil'/{print$1}' $TMPDIR/core-updates.txt` [ $bose ] && "Remote file md5sum: $rmd5" lmd5=`md5sum $TARG/$fil | awk '{print$1}'` [ $bose ] && "Local file md5sum: $lmd5" if [ "$rmd5" = "$lmd5" ]; then sayok "md5sum for $fil is good" else sayerror "md5sum for $fil is bad" echo "Removing file ..." [ -e $TARG/$fil ] && rm $TARG/$fil fi fi done echo echo "Updates complete." if [ "$TARG" = "$UPDF" ]; then green "Updates will be activated on next reboot." else echo "Updates are at $TARG" green "Please move them into your base folder." fi cleanup