From 4fe8b2ad0948d2e1ca1cb1ccfa11576b5bc9a4c7 Mon Sep 17 00:00:00 2001 From: OneCDOnly Date: Thu, 1 Aug 2024 05:59:55 +1000 Subject: [PATCH] general code refresh - update actions for compatibility with sherpa, - improve message format. --- build/SortMyQPKGs_240801.qpkg | Bin 0 -> 55764 bytes build/SortMyQPKGs_240801.qpkg.md5 | 1 + check.sh | 2 +- docs/changelog.txt | 4 +- qpkg.cfg | 2 +- shared/sortmyqpkgs(tmpfs).sh | 619 ------------------------------ shared/sortmyqpkgs.sh | 417 ++++++++++++++------ 7 files changed, 310 insertions(+), 735 deletions(-) create mode 100644 build/SortMyQPKGs_240801.qpkg create mode 100644 build/SortMyQPKGs_240801.qpkg.md5 delete mode 100755 shared/sortmyqpkgs(tmpfs).sh diff --git a/build/SortMyQPKGs_240801.qpkg b/build/SortMyQPKGs_240801.qpkg new file mode 100644 index 0000000000000000000000000000000000000000..b75d07daccb5c4431c3681602f474e5d9d40f613 GIT binary patch literal 55764 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 /dev/null 2>&1 - - # KLUDGE: `/dev/fd` isn't always created by QTS. - ln -fns /proc/self/fd /dev/fd - - local actual_alpha_pathfile='' - local actual_omega_pathfile='' - original_pathfile=/etc/config/qpkg.conf - working_pathfile=/sortmyqpkgs.tmp/qpkg.conf - - local -r BACKUP_PATH=$(/sbin/getcfg SHARE_DEF defVolMP -f /etc/config/def_share.info)/.qpkg_config_backup - readonly BACKUP_PATHFILE=$BACKUP_PATH/$QPKG_NAME.config.tar.gz - readonly LOG_GUI_PATHFILE=/home/httpd/$QPKG_NAME.log - readonly LOG_LINK_PATHFILE=/var/log/$QPKG_NAME.log - readonly QPKG_PATH=$(/sbin/getcfg "$QPKG_NAME" Install_Path -f /etc/config/qpkg.conf) - readonly CUSTOM_ALPHA_PATHFILE=$QPKG_PATH/ALPHA.custom - readonly CUSTOM_OMEGA_PATHFILE=$QPKG_PATH/OMEGA.custom - local -r DEFAULT_ALPHA_PATHFILE=$QPKG_PATH/ALPHA.default - local -r DEFAULT_OMEGA_PATHFILE=$QPKG_PATH/OMEGA.default - readonly LOG_REAL_PATHFILE=$QPKG_PATH/$QPKG_NAME.log - readonly LOG_TEMP_PATHFILE=$LOG_REAL_PATHFILE.tmp - readonly SERVICE_STATUS_PATHFILE=/var/run/$QPKG_NAME.last.operation - readonly SHUTDOWN_PATHFILE=/etc/init.d/shutdown_check.sh - - [[ -e $LOG_REAL_PATHFILE ]] || /bin/touch "$LOG_REAL_PATHFILE" - [[ ! -e $LOG_TEMP_PATHFILE ]] || rm -f "$LOG_TEMP_PATHFILE" - [[ -L $LOG_GUI_PATHFILE ]] || /bin/ln -s "$LOG_REAL_PATHFILE" "$LOG_GUI_PATHFILE" - [[ -L $LOG_LINK_PATHFILE ]] || /bin/ln -s "$LOG_REAL_PATHFILE" "$LOG_LINK_PATHFILE" - - if [[ -e $CUSTOM_ALPHA_PATHFILE ]]; then - actual_alpha_pathfile=$CUSTOM_ALPHA_PATHFILE - source_alpha=custom - elif [[ -e $DEFAULT_ALPHA_PATHFILE ]]; then - actual_alpha_pathfile=$DEFAULT_ALPHA_PATHFILE - source_alpha=default - else - echo 'ALPHA package list file not found' - SetServiceOperationResultFailed - exit 1 - fi - - if [[ -e $CUSTOM_OMEGA_PATHFILE ]]; then - actual_omega_pathfile=$CUSTOM_OMEGA_PATHFILE - source_omega=custom - elif [[ -e $DEFAULT_OMEGA_PATHFILE ]]; then - actual_omega_pathfile=$DEFAULT_OMEGA_PATHFILE - source_omega=default - else - echo 'OMEGA package list file not found' - SetServiceOperationResultFailed - exit 1 - fi - - while read -r package_ref comment; do - [[ -n $package_ref && $package_ref != \#* ]] || continue - PKGS_ALPHA_ORDERED+=("$package_ref") - done < "$actual_alpha_pathfile" - - while read -r package_ref comment; do - [[ -n $package_ref && $package_ref != \#* ]] || continue - PKGS_OMEGA_ORDERED+=("$package_ref") - done < "$actual_omega_pathfile" - - } - -BackupConfig() - { - - local a='' - - if [[ -e $CUSTOM_ALPHA_PATHFILE ]]; then - a=$(/usr/bin/basename "$CUSTOM_ALPHA_PATHFILE") - fi - - if [[ -e $CUSTOM_OMEGA_PATHFILE ]]; then - [[ -n $a ]] && a+=' ' - a+=$(/usr/bin/basename "$CUSTOM_OMEGA_PATHFILE") - fi - - if [[ -z $a ]]; then - /bin/touch "$BACKUP_PATHFILE" - echo 'nothing to backup' | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" - return 0 - fi - - /bin/tar --create --gzip --file="$BACKUP_PATHFILE" --directory="$QPKG_PATH" "$a" | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" - - return 0 - - } - -RestoreConfig() - { - - if [[ ! -s $BACKUP_PATHFILE ]]; then - echo 'unable to restore: backup file is unusable!' | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" - return 1 - fi - - /bin/tar --extract --gzip --file="$BACKUP_PATHFILE" --directory="$QPKG_PATH" | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" - - return 0 - - } - -ResetConfig() - { - - rm -f "$CUSTOM_ALPHA_PATHFILE" "$CUSTOM_OMEGA_PATHFILE" - - } - -ShowPreferredList() - { - - ShowSectionTitle 'Preferred order' - echo -e "< installed packages are indicated with '#' >\n" - ShowListsMarked - - } - -ShowPackagesBefore() - { - - ShowSectionTitle 'Original order' - ShowPackagesUnmarked - - } - -ShowPackagesCurrent() - { - - ShowSectionTitle 'Existing order' - ShowPackagesUnmarked - - } - -ShowPackagesAfter() - { - - ShowSectionTitle 'New order' - ShowPackagesUnmarked - - } - -ShowListsMarked() - { - - local a='' - local -i n=0 - - for pref in "${PKGS_ALPHA_ORDERED[@]}"; do - ((n++)); printf -v a '%02d' "$n" - - if (/bin/grep -qF "[$pref]" /etc/config/qpkg.conf); then - ShowLineMarked "$a" A "$pref" - else - ShowLineUnmarked "$a" A "$pref" - fi - done - - echo - ((n++)); printf -v a '%02d' "$n"; ShowLineUnmarked "$a" Φ '< existing unspecified packages go here >' - echo - - for pref in "${PKGS_OMEGA_ORDERED[@]}"; do - ((n++)); printf -v a '%02d' "$n" - - if (/bin/grep -qF "[$pref]" /etc/config/qpkg.conf); then - ShowLineMarked "$a" Ω "$pref" - else - ShowLineUnmarked "$a" Ω "$pref" - fi - done - - } - -ShowPackagesUnmarked() - { - - local a='' - local b='' - local c='' - local d='' - local e='' - local -i n=0 - - for a in $(/bin/grep '^\[' /etc/config/qpkg.conf); do - b=${a//[\[\]]} - ((n++)); printf -v c '%02d' "$n" - d=$(ShowLineUnmarked "$c" Φ "$b") - - for e in "${PKGS_ALPHA_ORDERED[@]}"; do - [[ $b = "$e" ]] || continue - d=$(ShowLineUnmarked "$c" A "$b") - break - done - - for e in "${PKGS_OMEGA_ORDERED[@]}"; do - [[ $b = "$e" ]] || continue - d=$(ShowLineUnmarked "$c" Ω "$b") - break - done - - echo -e "$d" - done - - } - -ShowSources() - { - - echo "ALPHA=$source_alpha, OMEGA=$source_omega" - - } - -SortPackages() - { - - local a='' - local -i i=0 - local b=$(dirname "$working_pathfile") - - echo -ne '\nsorting packages ... ' - - if [[ -d $b ]]; then - rm -rf "$working_pathfile" - else - mkdir "$b" - fi - - mount -t tmpfs -o size=1M tmpfs "$b" - cp "$original_pathfile" "$working_pathfile" - - # Read 'ALPHA' packages in-reverse and prepend each to /etc/config/qpkg.conf - for ((i=${#PKGS_ALPHA_ORDERED[@]}-1; i>=0; i--)); do - a=${PKGS_ALPHA_ORDERED[$i]} - /bin/grep -q "^\[$a\]" "$working_pathfile" && MoveConfigToTop "$a" - done - - # Now, read 'OMEGA' packages and append each to /etc/config/qpkg.conf - for a in "${PKGS_OMEGA_ORDERED[@]}"; do - /bin/grep -q "^\[$a\]" "$working_pathfile" && MoveConfigToBottom "$a" - done - - cp "$working_pathfile" "$original_pathfile" - umount "$b" - rmdir "$b" - - echo 'done' - - } - -MoveConfigToTop() - { - - # Move $1 to the top of qpkg.conf - - [[ -n ${1:-} ]] || return - - local a='' - - a=$(GetConfigBlock "$1") - [[ -n $a ]] || return - - /sbin/rmcfg "$1" -f "$working_pathfile" - echo -e "$a" > "$working_pathfile".tmp - /bin/cat "$working_pathfile" >> "$working_pathfile".tmp - mv "$working_pathfile".tmp "$working_pathfile" - - } - -MoveConfigToBottom() - { - - # Move $1 to the bottom of qpkg.conf - - [[ -n ${1:-} ]] || return - - local a='' - - a=$(GetConfigBlock "$1") - [[ -n $a ]] || return - - /sbin/rmcfg "$1" -f "$working_pathfile" - echo -e "\n${a}" >> "$working_pathfile" - - } - -GetConfigBlock() - { - - # Return the config block for the QPKG name specified as $1 - - [[ -n ${1:-} ]] || return - - local -i sl=0 # line number: start of specified config block - local -i ll=0 # line number: last line in file - local -i bl=0 # total lines in specified config block - local -i el=0 # line number: end of specified config block - - sl=$(/bin/grep -n "^\[$1\]" "$working_pathfile" | /usr/bin/cut -f1 -d':') - [[ -n $sl ]] || return - - ll=$(/usr/bin/wc -l < "$working_pathfile" | /bin/tr -d ' ') - bl=$(/usr/bin/tail -n$((ll-sl)) < "$working_pathfile" | /bin/grep -n '^\[' | /usr/bin/head -n1 | /usr/bin/cut -f1 -d':') - - [[ $bl -ne 0 ]] && el=$((sl+bl-1)) || el=$ll - [[ -n $el ]] || return - - echo -e "$(/bin/sed -n "$sl,${el}p" "$working_pathfile")" # Output this with 'echo' to strip trailing LFs from config block. - - } - -Upshift() - { - - # Move specified existing filename by incrementing extension value (upshift extension). - # If extension is not a number, then create new extension of '1' and copy file. - - # $1 = pathfilename to upshift - - [[ -n $1 ]] || return - [[ -e $1 ]] || return - - local ext='' - local dest='' - local -i rotate_limit=10 - - # Keep count of recursive calls. - local rec_limit=$((rotate_limit*2)) - local rec_count=0 - local rec_track_file=/tmp/${FUNCNAME[0]}.count - [[ -e $rec_track_file ]] && rec_count=$(<"$rec_track_file") - ((rec_count++)) - - if [[ $rec_count -gt $rec_limit ]]; then - echo 'recursive limit reached!' - rm "$rec_track_file" - exit 1 - fi - - echo "$rec_count" > "$rec_track_file" - - ext=${1##*.} - case $ext in - *[!0-9]*) # Specified file extension is not a number so add number and copy it. - dest="$1.1" - [[ -e $dest ]] && Upshift "$dest" - cp "$1" "$dest" - ;; - *) # Extension IS a number, so move it if possible. - if [[ $ext -lt $((rotate_limit-1)) ]]; then - ((ext++)); dest="${1%.*}.$ext" - [[ -e $dest ]] && Upshift "$dest" - mv "$1" "$dest" - else - rm "$1" - fi - esac - - [[ -e $rec_track_file ]] && { rec_count=$(<"$rec_track_file"); ((rec_count--)); echo "$rec_count" > "$rec_track_file" ;} - - } - -TrimLog() - { - - local -i max_ops=10 - local op_lines='' - local -i op_count=0 - local -i last_op_line_num=0 - - op_lines=$(/bin/grep -n '^──' "$LOG_REAL_PATHFILE") - op_count=$(/usr/bin/wc -l <<< "$op_lines") - - if [[ $op_count -gt $max_ops ]]; then - last_op_line_num=$(echo "$op_lines" | /usr/bin/head -n$((max_ops+1)) | /usr/bin/tail -n1 | /usr/bin/cut -f1 -d:) - /usr/bin/head -n"${last_op_line_num}" "$LOG_REAL_PATHFILE" > "$LOG_TEMP_PATHFILE" - mv "$LOG_TEMP_PATHFILE" "$LOG_REAL_PATHFILE" - fi - - } - -ShowLineUnmarked() - { - - # $1 = number - # $2 = symbol - # $3 = name - - echo "($1) ($2) $3" - - } - -ShowLineMarked() - { - - # $1 = number - # $2 = symbol - # $3 = name - - echo "($1)#($2) $3" - - } - -RecordOperationRequest() - { - - # $1 = Operation. - - local a='' - local -i b=0 - local c='' - - a="[$(/bin/date)] '$1' requested" - b=${#a} - printf -v c "%${b}s" - - echo -e "${c// /─}\n$QPKG_NAME ($(/sbin/getcfg "$QPKG_NAME" Build -f /etc/config/qpkg.conf))\n$a" >> "$LOG_TEMP_PATHFILE" - - LogWrite "'$1' requested" 0 - - } - -RecordOperationComplete() - { - - # $1 = Operation. - - echo -e "[$(/bin/date)] '$1' completed" >> "$LOG_TEMP_PATHFILE" - - LogWrite "'$1' completed" 0 - - } - -SetServiceOperationResultOK() - { - - SetServiceOperationResult ok - - } - -SetServiceOperationResultFailed() - { - - SetServiceOperationResult failed - - } - -SetServiceOperationResult() - { - - # $1 = Result of operation to recorded. - - [[ -n $1 && -n $SERVICE_STATUS_PATHFILE ]] && echo "$1" > "$SERVICE_STATUS_PATHFILE" - - } - -ShowSectionTitle() - { - - # $1 = Description. - - printf '\n * %s *\n' "$1" - - } - -CommitLog() - { - - echo -e "$(<"$LOG_TEMP_PATHFILE")\n$(<"$LOG_REAL_PATHFILE")" > "$LOG_REAL_PATHFILE" - - TrimLog - - } - -LogWrite() - { - - # $1 = Message to write into NAS system log. - # $2 = Event type: - # 0 : Information - # 1 : Warning - # 2 : Error - - log_tool --append "[$QPKG_NAME] $1" --type "$2" - - } - -Init - -case $1 in - autofix) - if [[ $(/sbin/getcfg "$QPKG_NAME" Enable -u -d FALSE -f /etc/config/qpkg.conf) != TRUE ]]; then - echo "$QPKG_NAME is disabled. You must first enable with: qpkg_service enable $QPKG_NAME" - SetServiceOperationResultFailed - exit 1 - fi - - RecordOperationRequest "$1" - ShowSources >> "$LOG_TEMP_PATHFILE" - Upshift /etc/config/qpkg.conf - ShowPackagesBefore >> "$LOG_TEMP_PATHFILE" - SortPackages - ShowPackagesAfter >> "$LOG_TEMP_PATHFILE" - RecordOperationComplete "$1" - CommitLog - ;; - b|backup) - RecordOperationRequest "$1" - BackupConfig - RecordOperationComplete "$1" - CommitLog - ;; - fix) - RecordOperationRequest "$1" - ShowSources | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" - Upshift /etc/config/qpkg.conf - ShowPackagesBefore | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" - SortPackages - ShowPackagesAfter | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" - RecordOperationComplete "$1" - CommitLog - echo -e '\nPackages will be started in this order during next boot-up.\n' - ;; - init|stop|restart) - # do nothing - /bin/sleep 1 - ;; - install|start) - if ! /bin/grep -q 'sortmyqpkgs.sh' $SHUTDOWN_PATHFILE; then - findtext='#backup logs' - inserttext='/etc/init.d/sortmyqpkgs.sh autofix' - /bin/sed -i "s|$findtext|$inserttext\n$findtext|" "$SHUTDOWN_PATHFILE" - fi - - if [[ $1 = install ]]; then - RecordOperationRequest "$1" - RecordOperationComplete "$1" - CommitLog - fi - ;; - pref) - ShowSources - ShowPreferredList - echo -e "\nTo re-order packages: $0 fix\n" - ;; - remove) - /bin/grep -q 'sortmyqpkgs.sh' "$SHUTDOWN_PATHFILE" && /bin/sed -i '/sortmyqpkgs.sh/d' "$SHUTDOWN_PATHFILE" - [[ -L $LOG_GUI_PATHFILE ]] && rm -f $LOG_GUI_PATHFILE - ;; - reset) - RecordOperationRequest "$1" - ResetConfig - RecordOperationComplete "$1" - CommitLog - ;; - restore) - RecordOperationRequest "$1" - RestoreConfig - RecordOperationComplete "$1" - CommitLog - ;; - s|status) - if /bin/grep -q 'sortmyqpkgs.sh' "$SHUTDOWN_PATHFILE"; then - echo active - exit 0 - else - echo inactive - exit 1 - fi - ;; - *) - echo -e "\nUsage: $0 {backup|fix|pref|reset|restore|status}\n" - ShowSources - ShowPackagesCurrent - echo -e "\nTo re-order packages: $0 fix\n" -esac - -rm -f "$LOG_TEMP_PATHFILE" -SetServiceOperationResultOK - -exit 0 diff --git a/shared/sortmyqpkgs.sh b/shared/sortmyqpkgs.sh index 6564216..433d736 100755 --- a/shared/sortmyqpkgs.sh +++ b/shared/sortmyqpkgs.sh @@ -1,29 +1,39 @@ #!/usr/bin/env bash ############################################################################ -# sortmyqpkgs.sh - Copyright 2017-2024 OneCD - one.cd.only@gmail.com - +# sortmyqpkgs.sh +# copyright 2017-2024 OneCD +# +# Contact: +# one.cd.only@gmail.com +# # This script is part of the 'SortMyQPKGs' package - +# # For more info: https://forum.qnap.com/viewtopic.php?f=320&t=133132 - +# # Available in the MyQNAP store: https://www.myqnap.org/product/sortmyqpkgs # Project source: https://github.com/OneCDOnly/SortMyQPKGs # Community forum: https://forum.qnap.com/viewtopic.php?f=320&t=133132 - +# # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. - +# # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. - +# # You should have received a copy of the GNU General Public License along with -# this program. If not, see http://www.gnu.org/licenses/. +# this program. If not, see http://www.gnu.org/licenses/ ############################################################################ +set -o nounset -o pipefail +shopt -s extglob +ln -fns /proc/self/fd /dev/fd # KLUDGE: `/dev/fd` isn't always created by QTS. + +readonly USER_ARGS_RAW=$* + Init() { @@ -35,9 +45,6 @@ Init() # KLUDGE: 'clean' the QTS 4.5.1+ App Center notifier status. [[ -e /sbin/qpkg_cli ]] && /sbin/qpkg_cli --clean "$QPKG_NAME" > /dev/null 2>&1 - # KLUDGE: `/dev/fd` isn't always created by QTS. - ln -fns /proc/self/fd /dev/fd - local actual_alpha_pathfile='' local actual_omega_pathfile='' @@ -52,7 +59,9 @@ Init() local -r DEFAULT_OMEGA_PATHFILE=$QPKG_PATH/OMEGA.default readonly LOG_REAL_PATHFILE=$QPKG_PATH/$QPKG_NAME.log readonly LOG_TEMP_PATHFILE=$LOG_REAL_PATHFILE.tmp - readonly SERVICE_STATUS_PATHFILE=/var/run/$QPKG_NAME.last.operation + readonly QPKG_VERSION=$(/sbin/getcfg $QPKG_NAME Version -f /etc/config/qpkg.conf) + readonly SERVICE_ACTION_PATHFILE=/var/log/$QPKG_NAME.action + readonly SERVICE_RESULT_PATHFILE=/var/log/$QPKG_NAME.result readonly SHUTDOWN_PATHFILE=/etc/init.d/shutdown_check.sh [[ -e $LOG_REAL_PATHFILE ]] || /bin/touch "$LOG_REAL_PATHFILE" @@ -68,7 +77,6 @@ Init() source_alpha=default else echo 'ALPHA package list file not found' - SetServiceOperationResultFailed exit 1 fi @@ -80,7 +88,6 @@ Init() source_omega=default else echo 'OMEGA package list file not found' - SetServiceOperationResultFailed exit 1 fi @@ -96,10 +103,67 @@ Init() } +StartQPKG() + { + + if IsNotQPKGEnabled; then + echo -e "This QPKG is disabled. Please enable it first with:\n\tqpkg_service enable $QPKG_NAME" + return 1 + else + AddHook + fi + + } + +Fix() + { + + RecordOperationRequest fix + ShowSources | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" + Upshift /etc/config/qpkg.conf + ShowPackagesBefore | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" + SortPackages + ShowPackagesAfter | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" + RecordOperationComplete fix + CommitLog + echo -e '\nPackages will be started in this order during next boot-up.\n' + + } + +AutoFix() + { + + RecordOperationRequest autofix + ShowSources >> "$LOG_TEMP_PATHFILE" + Upshift /etc/config/qpkg.conf + ShowPackagesBefore >> "$LOG_TEMP_PATHFILE" + SortPackages + ShowPackagesAfter >> "$LOG_TEMP_PATHFILE" + RecordOperationComplete autofix + CommitLog + + } + +StatusQPKG() + { + + if /bin/grep -q 'sortmyqpkgs.sh' "$SHUTDOWN_PATHFILE"; then + echo active + exit 0 + else + echo inactive + exit 1 + fi + + } + BackupConfig() { local a='' + local z=0 + + RecordOperationRequest backup if [[ -e $CUSTOM_ALPHA_PATHFILE ]]; then a=$(/usr/bin/basename "$CUSTOM_ALPHA_PATHFILE") @@ -113,36 +177,104 @@ BackupConfig() if [[ -z $a ]]; then /bin/touch "$BACKUP_PATHFILE" echo 'nothing to backup' | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" - return 0 + z=1 + else + /bin/tar --create --gzip --file="$BACKUP_PATHFILE" --directory="$QPKG_PATH" "$a" | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" fi - /bin/tar --create --gzip --file="$BACKUP_PATHFILE" --directory="$QPKG_PATH" "$a" | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" + RecordOperationComplete backup + CommitLog - return 0 + return $z } RestoreConfig() { + local z=0 + + RecordOperationRequest restore + if [[ ! -s $BACKUP_PATHFILE ]]; then echo 'unable to restore: backup file is unusable!' | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" - return 1 - fi - /bin/tar --extract --gzip --file="$BACKUP_PATHFILE" --directory="$QPKG_PATH" | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" + RecordOperationComplete restore + CommitLog + z=1 + else + /bin/tar --extract --gzip --file="$BACKUP_PATHFILE" --directory="$QPKG_PATH" | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" + RecordOperationComplete restore + CommitLog + fi - return 0 + return $z } ResetConfig() { + RecordOperationRequest reset rm -f "$CUSTOM_ALPHA_PATHFILE" "$CUSTOM_OMEGA_PATHFILE" + RecordOperationComplete reset + CommitLog } +AddHook() + { + + if ! /bin/grep -q 'sortmyqpkgs.sh' $SHUTDOWN_PATHFILE; then + findtext='#backup logs' + inserttext='/etc/init.d/sortmyqpkgs.sh autofix' + /bin/sed -i "s|$findtext|$inserttext\n$findtext|" "$SHUTDOWN_PATHFILE" + echo 'shutdown hook has been added' + fi + + } + +RemoveHook() + { + + if /bin/grep -q 'sortmyqpkgs.sh' "$SHUTDOWN_PATHFILE"; then + /bin/sed -i '/sortmyqpkgs.sh/d' "$SHUTDOWN_PATHFILE" + echo 'shutdown hook has been removed' + fi + + } + +ShowTitle() + { + + echo "$(ShowAsTitleName) $(ShowAsVersion)" + + } + +ShowAsTitleName() + { + + TextBrightWhite $QPKG_NAME + + } + +ShowAsVersion() + { + + printf '%s' "v$QPKG_VERSION" + + } + +ShowAsUsage() + { + + echo -e "\nUsage: $0 {backup|fix|pref|reset|restart|restore|status}\n" + ShowSources + ShowPackagesCurrent + echo -e "\nTo re-order packages:\n\t$0 fix" + + } + ShowPreferredList() { @@ -453,29 +585,6 @@ RecordOperationComplete() } -SetServiceOperationResultOK() - { - - SetServiceOperationResult ok - - } - -SetServiceOperationResultFailed() - { - - SetServiceOperationResult failed - - } - -SetServiceOperationResult() - { - - # $1 = Result of operation to recorded. - - [[ -n $1 && -n $SERVICE_STATUS_PATHFILE ]] && echo "$1" > "$SERVICE_STATUS_PATHFILE" - - } - ShowSectionTitle() { @@ -507,97 +616,181 @@ LogWrite() } +IsQPKGEnabled() + { + + # input: + # $1 = (optional) package name to check. If unspecified, default is $QPKG_NAME + + # output: + # $? = 0 : true + # $? = 1 : false + + [[ $(Lowercase "$(/sbin/getcfg "${1:-$QPKG_NAME}" Enable -d false -f /etc/config/qpkg.conf)") = true ]] + + } + +IsNotQPKGEnabled() + { + + # input: + # $1 = (optional) package name to check. If unspecified, default is $QPKG_NAME + + # output: + # $? = 0 : true + # $? = 1 : false + + ! IsQPKGEnabled "${1:-$QPKG_NAME}" + + } + +SetServiceAction() + { + + service_action=${1:-none} + CommitServiceAction + SetServiceResultAsInProgress + + } + +SetServiceResultAsOK() + { + + service_result=ok + CommitServiceResult + + } + +SetServiceResultAsFailed() + { + + service_result=failed + CommitServiceResult + + } + +SetServiceResultAsInProgress() + { + + # Selected action is in-progress and hasn't generated a result yet. + + service_result=in-progress + CommitServiceResult + + } + +CommitServiceAction() + { + + echo "$service_action" > "$SERVICE_ACTION_PATHFILE" + + } + +CommitServiceResult() + { + + echo "$service_result" > "$SERVICE_RESULT_PATHFILE" + + } + +TextBrightWhite() + { + + [[ -n ${1:-} ]] || return + + printf '\033[1;97m%s\033[0m' "$1" + + } + +Lowercase() + { + + /bin/tr 'A-Z' 'a-z' <<< "$1" + + } + Init -case $1 in - autofix) - if [[ $(/sbin/getcfg "$QPKG_NAME" Enable -u -d FALSE -f /etc/config/qpkg.conf) != TRUE ]]; then - echo "$QPKG_NAME is disabled. You must first enable with: qpkg_service enable $QPKG_NAME" - SetServiceOperationResultFailed - exit 1 - fi +user_arg=${USER_ARGS_RAW%% *} # Only process first argument. - RecordOperationRequest "$1" - ShowSources >> "$LOG_TEMP_PATHFILE" - Upshift /etc/config/qpkg.conf - ShowPackagesBefore >> "$LOG_TEMP_PATHFILE" - SortPackages - ShowPackagesAfter >> "$LOG_TEMP_PATHFILE" - RecordOperationComplete "$1" - CommitLog +case $user_arg in + autofix) + AutoFix ;; - b|backup) - RecordOperationRequest "$1" - BackupConfig - RecordOperationComplete "$1" - CommitLog + ?(-)b|?(--)backup) + SetServiceAction backup + + if BackupConfig; then + SetServiceResultAsOK + else + SetServiceResultAsFailed + fi ;; - fix) - RecordOperationRequest "$1" - ShowSources | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" - Upshift /etc/config/qpkg.conf - ShowPackagesBefore | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" - SortPackages - ShowPackagesAfter | /usr/bin/tee -a "$LOG_TEMP_PATHFILE" - RecordOperationComplete "$1" - CommitLog - echo -e '\nPackages will be started in this order during next boot-up.\n' + ?(--)fix) + Fix ;; - init|stop|restart) - # do nothing + init|?(--)stop) # Ignore these. /bin/sleep 1 ;; - install|start) - if ! /bin/grep -q 'sortmyqpkgs.sh' $SHUTDOWN_PATHFILE; then - findtext='#backup logs' - inserttext='/etc/init.d/sortmyqpkgs.sh autofix' - /bin/sed -i "s|$findtext|$inserttext\n$findtext|" "$SHUTDOWN_PATHFILE" - fi + ?(--)restart) + SetServiceAction restart - if [[ $1 = install ]]; then - RecordOperationRequest "$1" - RecordOperationComplete "$1" - CommitLog + if RemoveHook && StartQPKG; then + SetServiceResultAsOK + else + SetServiceResultAsFailed fi ;; - pref) + ?(--)pref) ShowSources ShowPreferredList echo -e "\nTo re-order packages: $0 fix\n" ;; remove) - /bin/grep -q 'sortmyqpkgs.sh' "$SHUTDOWN_PATHFILE" && /bin/sed -i '/sortmyqpkgs.sh/d' "$SHUTDOWN_PATHFILE" - [[ -L $LOG_GUI_PATHFILE ]] && rm -f $LOG_GUI_PATHFILE + RemoveHook ;; - reset) - RecordOperationRequest "$1" + ?(--)reset) ResetConfig - RecordOperationComplete "$1" - CommitLog ;; - restore) - RecordOperationRequest "$1" - RestoreConfig - RecordOperationComplete "$1" - CommitLog + ?(--)restore) + SetServiceAction restore + + if RestoreConfig; then + SetServiceResultAsOK + else + SetServiceResultAsFailed + fi + ;; + install) + SetServiceAction install + RecordOperationRequest install + + if StartQPKG; then + SetServiceResultAsOK + CommitLog + else + SetServiceResultAsFailed + fi + + RecordOperationComplete install + ;; + ?(--)start) + SetServiceAction start + + if StartQPKG; then + SetServiceResultAsOK + else + SetServiceResultAsFailed + fi + ;; + ?(-)s|?(--)status) + StatusQPKG ;; - s|status) - if /bin/grep -q 'sortmyqpkgs.sh' "$SHUTDOWN_PATHFILE"; then - echo active - exit 0 - else - echo inactive - exit 1 - fi - ;; *) - echo -e "\nUsage: $0 {backup|fix|pref|reset|restore|status}\n" - ShowSources - ShowPackagesCurrent - echo -e "\nTo re-order packages: $0 fix\n" + ShowTitle + ShowAsUsage esac rm -f "$LOG_TEMP_PATHFILE" -SetServiceOperationResultOK exit 0