arc-addons/deduplication/all/usr/bin/deduplication.sh
AuxXxilium bc357615ef deduplication: update
Signed-off-by: AuxXxilium <info@auxxxilium.tech>
2024-05-29 23:15:18 +02:00

975 lines
33 KiB
Bash
Executable File

#!/usr/bin/env bash
#-------------------------------------------------------------------------------
# Enables data deduplication with non-Synology drives and unsupported NAS models
#
# Github: https://github.com/007revad/Synology_enable_Deduplication
# Script verified at https://www.shellcheck.net/
#
# To run in a shell (replace /volume1/scripts/ with path to script):
# sudo /volume1/scripts/syno_enable_dedupe.sh
#-------------------------------------------------------------------------------
scriptver="v1.3.25"
script=Synology_enable_Deduplication
repo="007revad/Synology_enable_Deduplication"
scriptname=syno_enable_dedupe
# Check BASH variable is bash
if [ ! "$(basename "$BASH")" = bash ]; then
echo "This is a bash script. Do not run it with $(basename "$BASH")"
printf \\a
exit 1
fi
ding(){
printf \\a
}
usage(){
cat <<EOF
$script $scriptver - by 007revad
Usage: $(basename "$0") [options]
Options:
-c, --check Check value in file and backup file
-r, --restore Undo all changes made by the script
-t, --tiny Enable tiny data deduplication (only needs 4GB RAM)
DSM 7.2.1 and later only
--hdd Enable data deduplication for HDDs (dangerous)
-e, --email Disable colored text in output for scheduler emails
--autoupdate=AGE Auto update script (useful when script is scheduled)
AGE is how many days old a release must be before
auto-updating. AGE must be a number: 0 or greater
-s, --skip Skip memory amount check (for testing)
-h, --help Show this help message
-v, --version Show the script version
EOF
exit 0
}
scriptversion(){
cat <<EOF
$script $scriptver - by 007revad
See https://github.com/$repo
EOF
exit 0
}
# Save options used
args=("$@")
autoupdate=""
# Check for flags with getopt
if options="$(getopt -o abcdefghijklmnopqrstuvwxyz0123456789 -l \
skip,check,restore,help,version,tiny,hdd,email,autoupdate:,log,debug -- "$@")"; then
eval set -- "$options"
while true; do
case "${1,,}" in
-h|--help) # Show usage options
usage
;;
-v|--version) # Show script version
scriptversion
;;
-t|--tiny) # Enable tiny deduplication
tiny=yes
;;
--hdd) # Enable deduplication for HDDs (dangerous)
hdd=yes
;;
-s|--skip) # Skip memory amount check (for testing)
skip=yes
;;
-l|--log) # Log
#log=yes
;;
-d|--debug) # Show and log debug info
debug=yes
;;
-c|--check) # Check value in file and backup file
check=yes
break
;;
-r|--restore) # Restore from backups to undo changes
restore=yes
break
;;
-e|--email) # Disable colour text in task scheduler emails
color=no
;;
--autoupdate) # Auto update script
autoupdate=yes
if [[ $2 =~ ^[0-9]+$ ]]; then
delay="$2"
shift
else
delay="0"
fi
;;
--)
shift
break
;;
*) # Show usage options
echo -e "Invalid option '$1'\n"
usage "$1"
;;
esac
shift
done
else
echo
usage
fi
if [[ $debug == "yes" ]]; then
set -x
export PS4='`[[ $? == 0 ]] || echo "\e[1;31;40m($?)\e[m\n "`:.$LINENO:'
fi
# Shell Colors
if [[ $color != "no" ]]; then
#Black='\e[0;30m' # ${Black}
Red='\e[0;31m' # ${Red}
#Green='\e[0;32m' # ${Green}
Yellow='\e[0;33m' # ${Yellow}
#Blue='\e[0;34m' # ${Blue}
#Purple='\e[0;35m' # ${Purple}
Cyan='\e[0;36m' # ${Cyan}
#White='\e[0;37m' # ${White}
Error='\e[41m' # ${Error}
Off='\e[0m' # ${Off}
else
echo "" # For task scheduler email readability
fi
# Check script is running as root
if [[ $( whoami ) != "root" ]]; then
ding
echo -e "${Error}ERROR${Off} This script must be run as sudo or root!"
exit 1
fi
# Get DSM major, minor and micro versions
major=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION majorversion)
minor=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION minorversion)
micro=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION micro)
# Get NAS model
model=$(cat /proc/sys/kernel/syno_hw_version)
#modelname="$model"
# Show script version
#echo -e "$script $scriptver\ngithub.com/$repo\n"
echo "$script $scriptver"
# Get DSM full version
productversion=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION productversion)
buildphase=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION buildphase)
buildnumber=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION buildnumber)
smallfixnumber=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION smallfixnumber)
# Show DSM full version and model
if [[ $buildphase == GM ]]; then buildphase=""; fi
if [[ $smallfixnumber -gt "0" ]]; then smallfix="-$smallfixnumber"; fi
echo -e "$model DSM $productversion-$buildnumber$smallfix $buildphase\n"
# Get StorageManager version
storagemgrver=$(/usr/syno/bin/synopkg version StorageManager)
# Show StorageManager version
if [[ $storagemgrver ]]; then echo -e "StorageManager $storagemgrver \n"; fi
# Show options used
if [[ ${#args[@]} -gt "0" ]]; then
#echo -e "Using options: ${args[*]}\n"
echo -e "Using options: ${args[*]}"
fi
if [[ $major$minor$micro -lt "701" ]]; then
ding
#echo "This script only works for DSM 7.0.1 and later."
echo "Btrfs Data Deduplication only works in DSM 7.0.1 and later."
exit 1
fi
# Check model (and DSM version for that model) supports dedupe
if [[ ! -f /usr/syno/sbin/synobtrfsdedupe ]]; then
arch=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/synoinfo.conf platform_name)
#echo "Your model or DSM version does not support Btrfs Data Deduplication."
echo "Models with $arch CPUs do not support Btrfs Data Deduplication."
echo "Only models with V1000, R1000, Geminilake, Broadwellnkv2, "
echo "Broadwellnk, Broadwell, Purley and Epyc7002 CPUs are supported."
exit
fi
#------------------------------------------------------------------------------
# Check latest release with GitHub API
syslog_set(){
if [[ ${1,,} == "info" ]] || [[ ${1,,} == "warn" ]] || [[ ${1,,} == "err" ]]; then
if [[ $autoupdate == "yes" ]]; then
# Add entry to Synology system log
/usr/syno/bin/synologset1 sys "$1" 0x11100000 "$2"
fi
fi
}
# Get latest release info
# Curl timeout options:
# https://unix.stackexchange.com/questions/94604/does-curl-have-a-timeout
release=$(curl --silent -m 10 --connect-timeout 5 \
"https://api.github.com/repos/$repo/releases/latest")
# Release version
tag=$(echo "$release" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
shorttag="${tag:1}"
# Release published date
published=$(echo "$release" | grep '"published_at":' | sed -E 's/.*"([^"]+)".*/\1/')
published="${published:0:10}"
published=$(date -d "$published" '+%s')
# Today's date
now=$(date '+%s')
# Days since release published
age=$(((now - published)/(60*60*24)))
# Get script location
# https://stackoverflow.com/questions/59895/
source=${BASH_SOURCE[0]}
while [ -L "$source" ]; do # Resolve $source until the file is no longer a symlink
scriptpath=$( cd -P "$( dirname "$source" )" >/dev/null 2>&1 && pwd )
source=$(readlink "$source")
# If $source was a relative symlink, we need to resolve it
# relative to the path where the symlink file was located
[[ $source != /* ]] && source=$scriptpath/$source
done
scriptpath=$( cd -P "$( dirname "$source" )" >/dev/null 2>&1 && pwd )
scriptfile=$( basename -- "$source" )
echo "Running from: ${scriptpath}/$scriptfile"
# Warn if script located on M.2 drive
scriptvol=$(echo "$scriptpath" | cut -d"/" -f2)
vg=$(lvdisplay | grep /volume_"${scriptvol#volume}" | cut -d"/" -f3)
md=$(pvdisplay | grep -B 1 -E '[ ]'"$vg" | grep /dev/ | cut -d"/" -f3)
if cat /proc/mdstat | grep "$md" | grep nvme >/dev/null; then
echo -e "${Yellow}WARNING${Off} Don't store this script on an NVMe volume!"
fi
cleanup_tmp(){
cleanup_err=
# Delete downloaded .tar.gz file
if [[ -f "/tmp/$script-$shorttag.tar.gz" ]]; then
if ! rm "/tmp/$script-$shorttag.tar.gz"; then
echo -e "${Error}ERROR${Off} Failed to delete"\
"downloaded /tmp/$script-$shorttag.tar.gz!" >&2
cleanup_err=1
fi
fi
# Delete extracted tmp files
if [[ -d "/tmp/$script-$shorttag" ]]; then
if ! rm -r "/tmp/$script-$shorttag"; then
echo -e "${Error}ERROR${Off} Failed to delete"\
"downloaded /tmp/$script-$shorttag!" >&2
cleanup_err=1
fi
fi
# Add warning to DSM log
if [[ -z $cleanup_err ]]; then
syslog_set warn "$script update failed to delete tmp files"
fi
}
if ! printf "%s\n%s\n" "$tag" "$scriptver" |
sort --check=quiet --version-sort >/dev/null ; then
echo -e "\n${Cyan}There is a newer version of this script available.${Off}"
echo -e "Current version: ${scriptver}\nLatest version: $tag"
scriptdl="$scriptpath/$script-$shorttag"
if [[ -f ${scriptdl}.tar.gz ]] || [[ -f ${scriptdl}.zip ]]; then
# They have the latest version tar.gz downloaded but are using older version
echo "You have the latest version downloaded but are using an older version"
sleep 10
elif [[ -d $scriptdl ]]; then
# They have the latest version extracted but are using older version
echo "You have the latest version extracted but are using an older version"
sleep 10
else
if [[ $autoupdate == "yes" ]]; then
if [[ $age -gt "$delay" ]] || [[ $age -eq "$delay" ]]; then
echo "Downloading $tag"
reply=y
else
echo "Skipping as $tag is less than $delay days old."
fi
else
echo -e "${Cyan}Do you want to download $tag now?${Off} [y/n]"
read -r -t 30 reply
fi
if [[ ${reply,,} == "y" ]]; then
# Delete previously downloaded .tar.gz file and extracted tmp files
cleanup_tmp
if cd /tmp; then
url="https://github.com/$repo/archive/refs/tags/$tag.tar.gz"
if ! curl -JLO -m 30 --connect-timeout 5 "$url"; then
echo -e "${Error}ERROR${Off} Failed to download"\
"$script-$shorttag.tar.gz!"
syslog_set warn "$script $tag failed to download"
else
if [[ -f /tmp/$script-$shorttag.tar.gz ]]; then
# Extract tar file to /tmp/<script-name>
if ! tar -xf "/tmp/$script-$shorttag.tar.gz" -C "/tmp"; then
echo -e "${Error}ERROR${Off} Failed to"\
"extract $script-$shorttag.tar.gz!"
syslog_set warn "$script failed to extract $script-$shorttag.tar.gz!"
else
# Set script sh files as executable
if ! chmod a+x "/tmp/$script-$shorttag/"*.sh ; then
permerr=1
echo -e "${Error}ERROR${Off} Failed to set executable permissions"
syslog_set warn "$script failed to set permissions on $tag"
fi
# Copy new script sh file to script location
if ! cp -p "/tmp/$script-$shorttag/${scriptname}.sh" "${scriptpath}/${scriptfile}";
then
copyerr=1
echo -e "${Error}ERROR${Off} Failed to copy"\
"$script-$shorttag sh file(s) to:\n $scriptpath/${scriptfile}"
syslog_set warn "$script failed to copy $tag to script location"
fi
# Copy new CHANGES.txt file to script location (if script on a volume)
if [[ $scriptpath =~ /volume* ]]; then
# Set permissions on CHANGES.txt
if ! chmod 664 "/tmp/$script-$shorttag/CHANGES.txt"; then
permerr=1
echo -e "${Error}ERROR${Off} Failed to set permissions on:"
echo "$scriptpath/CHANGES.txt"
fi
# Copy new CHANGES.txt file to script location
if ! cp -p "/tmp/$script-$shorttag/CHANGES.txt"\
"${scriptpath}/${scriptname}_CHANGES.txt";
then
if [[ $autoupdate != "yes" ]]; then copyerr=1; fi
echo -e "${Error}ERROR${Off} Failed to copy"\
"$script-$shorttag/CHANGES.txt to:\n $scriptpath"
else
changestxt=" and changes.txt"
fi
fi
# Delete downloaded tmp files
cleanup_tmp
# Notify of success (if there were no errors)
if [[ $copyerr != 1 ]] && [[ $permerr != 1 ]]; then
echo -e "\n$tag ${scriptfile}$changestxt downloaded to: ${scriptpath}\n"
syslog_set info "$script successfully updated to $tag"
# Reload script
printf -- '-%.0s' {1..79}; echo # print 79 -
exec "${scriptpath}/$scriptfile" "${args[@]}"
else
syslog_set warn "$script update to $tag had errors"
fi
fi
else
echo -e "${Error}ERROR${Off}"\
"/tmp/$script-$shorttag.tar.gz not found!"
#ls /tmp | grep "$script" # debug
syslog_set warn "/tmp/$script-$shorttag.tar.gz not found"
fi
fi
cd "$scriptpath" || echo -e "${Error}ERROR${Off} Failed to cd to script location!"
else
echo -e "${Error}ERROR${Off} Failed to cd to /tmp!"
syslog_set warn "$script update failed to cd to /tmp"
fi
fi
fi
fi
#------------------------------------------------------------------------------
# Set file variables
synoinfo="/etc.defaults/synoinfo.conf"
synoinfo2="/etc/synoinfo.conf"
strgmgr="/var/packages/StorageManager/target/ui/storage_panel.js"
libhw="/usr/lib/libhwcontrol.so.1"
if [[ ! -f ${libhw} ]]; then
ding
echo -e "${Error}ERROR${Off} $(basename -- $libhw) not found!"
exit 1
fi
rebootmsg(){
# Reboot prompt
echo -e "\n${Cyan}The Synology needs to restart.${Off}"
echo -e "Type ${Cyan}yes${Off} to reboot now."
echo -e "Type anything else to quit (if you will restart it yourself)."
read -r -t 10 answer
if [[ ${answer,,} != "yes" ]]; then exit; fi
# # Reboot in the background so user can see DSM's "going down" message
# reboot &
if [[ -x /usr/syno/sbin/synopoweroff ]]; then
/usr/syno/sbin/synopoweroff -r || reboot
else
reboot
fi
}
reloadmsg(){
# Reload browser prompt
echo -e "\nFinished"
echo -e "\nIf you have DSM open in a browser you need to"
echo "refresh the browser window or tab."
exit
}
#----------------------------------------------------------
# Restore changes from backup file
compare_md5(){
# $1 is file 1
# $2 is file 2
if [[ -f "$1" ]] && [[ -f "$2" ]]; then
if [[ $(md5sum -b "$1" | awk '{print $1}') == $(md5sum -b "$2" | awk '{print $1}') ]];
then
return 0
else
return 1
fi
else
restoreerr=$((restoreerr+1))
return 2
fi
}
if [[ $restore == "yes" ]]; then
echo ""
if [[ -f ${synoinfo}.bak ]] || [[ -f ${libhw}.bak ]] ||\
[[ -f ${strgmgr}.${storagemgrver} ]]; then
# Restore synoinfo.conf from backup
if [[ -f ${synoinfo}.bak ]]; then
keyvalues=("support_btrfs_dedupe" "support_tiny_btrfs_dedupe")
for v in "${!keyvalues[@]}"; do
defaultval="$(/usr/syno/bin/synogetkeyvalue ${synoinfo}.bak "${keyvalues[v]}")"
if [[ -z $defaultval ]]; then defaultval="no"; fi
currentval="$(/usr/syno/bin/synogetkeyvalue ${synoinfo} "${keyvalues[v]}")"
if [[ $currentval != "$defaultval" ]]; then
if /usr/syno/bin/synosetkeyvalue "$synoinfo" "${keyvalues[v]}" "$defaultval";
then
restored="yes"
echo "Restored ${keyvalues[v]} = $defaultval"
fi
fi
/usr/syno/bin/synosetkeyvalue "$synoinfo2" "${keyvalues[v]}" "$defaultval"
done
fi
# Restore storage_panel.js from backup
if [[ -f "${strgmgr}.$storagemgrver" ]]; then
string1="(SYNO.SDS.StorageUtils.supportBtrfsDedupe)"
string2="(SYNO.SDS.StorageUtils.supportBtrfsDedupe&&e.dedup_info.show_config_btn)"
if grep -o "$string1" "${strgmgr}" >/dev/null; then
# Restore string in file
sed -i "s/${string1}/${string2/&&/\\&\\&}/g" "$strgmgr"
# Check we restored string in file
if grep -o "string2" "${strgmgr}" >/dev/null; then
restored="yes"
echo "Restored $(basename -- "$strgmgr")"
else
restoreerr=1
echo -e "${Error}ERROR${Off} Failed to restore $(basename -- "$strgmgr")!"
fi
fi
else
echo "No backup of $(basename -- "$strgmgr") found."
fi
if [[ -f "${libhw}.bak" ]]; then
# Check if backup libhwcontrol size matches
# in case backup is from previous DSM version
filesize=$(wc -c "${libhw}" | awk '{print $1}')
filebaksize=$(wc -c "${libhw}.bak" | awk '{print $1}')
if [[ ! $filesize -eq "$filebaksize" ]]; then
echo -e "${Yellow}WARNING Backup file size is different to file!${Off}"
echo "Do you want to restore this backup? [yes/no]:"
read -r -t 20 answer
if [[ $answer != "yes" ]]; then
exit
fi
fi
# Restore from backup
if ! compare_md5 "$libhw".bak "$libhw"; then
if cp -p "$libhw".bak "$libhw" ; then
restored="yes"
reboot="yes"
echo "Restored $(basename -- "$libhw")"
else
restoreerr=1
echo -e "${Error}ERROR${Off} Failed to restore $(basename -- "$libhw")!"
fi
fi
else
echo "No backup of $(basename -- "$libhw") found."
fi
if [[ -z $restoreerr ]]; then
if [[ $restored == "yes" ]]; then
echo -e "\nRestore successful."
reloadmsg
else
echo -e "Nothing to restore."
fi
fi
if [[ $reboot == "yes" ]]; then
rebootmsg
fi
else
echo -e "No backups to restore from."
fi
exit
fi
#----------------------------------------------------------
# Check NAS has enough memory
if [[ $restore != "yes" ]] && [[ $skip != "yes" ]]; then
IFS=$'\n' read -r -d '' -a array < <(dmidecode -t memory | grep -E "[Ss]ize: [0-9]+ [MG]{1}[B]{1}$")
if [[ ${#array[@]} -gt "0" ]]; then
num="0"
while [[ $num -lt "${#array[@]}" ]]; do
memcheck=$(printf %s "${array[num]}" | awk '{print $1}')
if [[ ${memcheck,,} == "size:" ]]; then
ramsize=$(printf %s "${array[num]}" | awk '{print $2}')
bytes=$(printf %s "${array[num]}" | awk '{print $3}')
if [[ $ramsize =~ ^[0-9]+$ ]]; then # Check $ramsize is numeric
if [[ $bytes == "GB" ]]; then # DSM 7.2 dmidecode returned GB
ramsize=$((ramsize * 1024)) # Convert to MB
fi
if [[ $ramtotal ]]; then
ramtotal=$((ramtotal +ramsize))
else
ramtotal="$ramsize"
fi
fi
fi
num=$((num +1))
done
ramgb=$((ramtotal / 1024))
if [[ $storagemgrver ]]; then
# Only DSM 7.2.1 and later supports tiny dedupe
if [[ $tiny == "yes" ]] || [[ $ramtotal -lt 16384 ]]; then
ramneeded="4096" # Tiny dedupe only needs 4GB ram
tiny="yes"
else
ramneeded="16384" # Needs 16GB ram
tiny=""
fi
else
ramneeded="16384" # Needs 16GB ram
tiny=""
fi
if [[ $ramtotal -lt "$ramneeded" ]]; then
ding
echo -e "\n${Error}ERROR${Off} Not enough memory installed for deduplication: $ramgb GB"
exit 1
else
echo -e "\nNAS has $ramgb GB of memory."
fi
else
ding
echo -e "\n${Error}ERROR${Off} Unable to determine the amount of installed memory!"
exit 1
fi
fi
#----------------------------------------------------------
# Edit libhwcontrol.so.1
findbytes(){
# Get decimal position of matching hex string
match=$(od -v -t x1 "$1" |
sed 's/[^ ]* *//' |
tr '\012' ' ' |
grep -b -i -o "$hexstring" |
#grep -b -i -o "$hexstring ".. |
cut -d ':' -f 1 |
xargs -I % expr % / 3)
# Convert decimal position of matching hex string to hex
array=("$match")
if [[ ${#array[@]} -gt "1" ]]; then
num="0"
while [[ $num -lt "${#array[@]}" ]]; do
poshex=$(printf "%x" "${array[$num]}")
if [[ $debug == "yes" ]]; then
echo "${array[$num]} = $poshex" # debug
fi
seek="${array[$num]}"
xxd=$(xxd -u -l 12 -s "$seek" "$1")
#echo "$xxd" # debug
if [[ $debug == "yes" ]]; then
printf %s "$xxd" | cut -d" " -f1-7
else
printf %s "$xxd" | cut -d" " -f1-7 >/dev/null
fi
bytes=$(printf %s "$xxd" | cut -d" " -f6)
#echo "$bytes" # debug
num=$((num +1))
done
elif [[ -n $match ]]; then
poshex=$(printf "%x" "$match")
if [[ $debug == "yes" ]]; then
echo "$match = $poshex" # debug
fi
seek="$match"
xxd=$(xxd -u -l 12 -s "$seek" "$1")
#echo "$xxd" # debug
if [[ $debug == "yes" ]]; then
printf %s "$xxd" | cut -d" " -f1-7
else
printf %s "$xxd" | cut -d" " -f1-7 >/dev/null
fi
bytes=$(printf %s "$xxd" | cut -d" " -f6)
#echo "$bytes" # debug
else
bytes=""
fi
}
# Check value in file and backup file
if [[ $check == "yes" ]]; then
err=0
# Check if deduplication enabled in synoinfo.conf
sbd=support_btrfs_dedupe
stbd=support_tiny_btrfs_dedupe
setting="$(/usr/syno/bin/synogetkeyvalue "$synoinfo" ${sbd})"
setting2="$(/usr/syno/bin/synogetkeyvalue "$synoinfo" ${stbd})"
# if [[ $tiny != "yes" ]] || [[ $ramtotal -lt 16384 ]]; then
if [[ $setting == "yes" ]]; then
echo -e "\nBtrfs Data Deduplication is ${Cyan}enabled${Off}."
else
echo -e "\nBtrfs Data Deduplication is ${Cyan}not${Off} enabled."
fi
# else
if [[ $setting2 == "yes" ]]; then
echo -e "\nTiny Btrfs Data Deduplication is ${Cyan}enabled${Off}."
else
echo -e "\nTiny Btrfs Data Deduplication is ${Cyan}not${Off} enabled."
fi
# fi
# DSM 7.2.1 only and only if --hdd option used
# Dedupe config button for HDDs and 2.5 inch SSDs in DSM 7.2.1
if [[ -f "$strgmgr" ]] && [[ $hdd == "yes" ]]; then
# StorageManager package is installed and --hdd option used
if ! grep '&&e.dedup_info.show_config_btn' "$strgmgr" >/dev/null; then
echo -e "\nDedupe config menu for HDDs and 2.5\" SSDs already enabled."
else
echo -e "\nDedupe config menu for HDDs and 2.5\" SSDs is ${Cyan}not${Off} enabled."
fi
fi
# Check value in file
echo -e "\nChecking non-Synology drive supported."
hexstring="80 3E 00 B8 01 00 00 00 90 90 48 8B"
findbytes "$libhw"
if [[ $bytes == "9090" ]]; then
echo -e "File is already edited."
else
hexstring="80 3E 00 B8 01 00 00 00 75 2. 48 8B"
findbytes "$libhw"
if [[ $bytes =~ "752"[0-9] ]]; then
echo -e "File is ${Cyan}not${Off} edited."
else
echo -e "${Red}hex string not found!${Off}"
err=1
fi
fi
# Check value in backup file
if [[ -f ${libhw}.bak ]]; then
echo -e "\nChecking value in backup file."
hexstring="80 3E 00 B8 01 00 00 00 75 2. 48 8B"
findbytes "${libhw}.bak"
if [[ $bytes =~ "752"[0-9] ]]; then
echo -e "Backup file is okay."
else
hexstring="80 3E 00 B8 01 00 00 00 90 90 48 8B"
findbytes "${libhw}.bak"
if [[ $bytes == "9090" ]]; then
echo -e "${Red}Backup file has been edited!${Off}"
else
echo -e "${Red}hex string not found!${Off}"
err=1
fi
fi
else
echo "No backup file found."
fi
exit "$err"
fi
#----------------------------------------------------------
# Backup libhwcontrol
if [[ ! -f ${libhw}.bak ]]; then
if cp -p "$libhw" "$libhw".bak ; then
echo "Backup successful."
else
ding
echo -e "${Error}ERROR${Off} Backup failed!"
exit 1
fi
else
# Check if backup size matches file size
filesize=$(wc -c "$libhw" | awk '{print $1}')
filebaksize=$(wc -c "${libhw}.bak" | awk '{print $1}')
if [[ ! $filesize -eq "$filebaksize" ]]; then
echo -e "${Yellow}WARNING Backup file size is different to file!${Off}"
echo "Maybe you've updated DSM since last running this script?"
echo "Renaming file.bak to file.bak.old"
mv "${libhw}.bak" "$libhw".bak.old
if cp -p "$libhw" "$libhw".bak ; then
echo "Backup successful."
else
ding
echo -e "${Error}ERROR${Off} Backup failed!"
exit 1
fi
#else
# echo "$(basename -- "$libhw") already backed up."
fi
fi
#----------------------------------------------------------
# Edit libhwcontrol
#echo -e "\nChecking $(basename -- "$libhw")."
# Check if the file is already edited
hexstring="80 3E 00 B8 01 00 00 00 90 90 48 8B"
findbytes "$libhw"
if [[ $bytes == "9090" ]]; then
#echo -e "\n$(basename -- "$libhw") already edited."
echo -e "\nNon-Synology drive support already enabled."
else
# Check if the file is okay for editing
hexstring="80 3E 00 B8 01 00 00 00 75 2. 48 8B"
findbytes "$libhw"
if ! [[ $bytes =~ "752"[0-9] ]]; then
ding
echo -e "\n${Red}hex string not found!${Off}"
exit 1
fi
# Replace bytes in file
posrep=$(printf "%x\n" $((0x${poshex}+8)))
if ! printf %s "${posrep}: 9090" | xxd -r - "$libhw"; then
ding
echo -e "${Error}ERROR${Off} Failed to edit $(basename -- "$libhw")!"
exit 1
else
# Check if libhwcontrol.so.1 was successfully edited
#echo -e "\nChecking if file was successfully edited."
hexstring="80 3E 00 B8 01 00 00 00 90 90 48 8B"
findbytes "$libhw"
if [[ $bytes == "9090" ]]; then
#echo -e "File successfully edited."
echo -e "\nEnabled non-Synology drive support."
#echo -e "\n${Cyan}You can now enable data deduplication"\
# "pool in Storage Manager.${Off}"
reboot="yes"
fi
fi
fi
#------------------------------------------------------------------------------
# Edit /etc.defaults/synoinfo.conf
# Backup synoinfo.conf if needed
if [[ ! -f ${synoinfo}.bak ]]; then
if cp -p "$synoinfo" "$synoinfo.bak"; then
echo -e "\nBacked up $(basename -- "$synoinfo")" >&2
else
ding
echo -e "\n${Error}ERROR 5${Off} Failed to backup $(basename -- "$synoinfo")!"
exit 1
fi
fi
enabled=""
sbd=support_btrfs_dedupe
stbd=support_tiny_btrfs_dedupe
# Enable dedupe support if needed
setting="$(/usr/syno/bin/synogetkeyvalue "$synoinfo" ${sbd})"
if [[ $tiny != "yes" ]]; then
if [[ ! $setting ]] || [[ $setting == "no" ]]; then
if [[ -n $sbd ]]; then
/usr/syno/bin/synosetkeyvalue "$synoinfo" "$sbd" yes
/usr/syno/bin/synosetkeyvalue "$synoinfo2" "$sbd" yes
enabled="yes"
fi
elif [[ $setting == "yes" ]]; then
echo -e "\nBtrfs Data Deduplication already enabled."
fi
# Disable support_tiny_btrfs_dedupe
if [[ $enabled == "yes" ]]; then
if grep "$stbd" "$synoinfo" >/dev/null; then
/usr/syno/bin/synosetkeyvalue "$synoinfo" "$stbd" no
fi
if grep "$stbd" "$synoinfo2" >/dev/null; then
/usr/syno/bin/synosetkeyvalue "$synoinfo2" "$stbd" no
fi
fi
fi
# Enable tiny dedupe support if needed
setting="$(/usr/syno/bin/synogetkeyvalue "$synoinfo" ${stbd})"
if [[ $tiny == "yes" ]]; then
if [[ ! $setting ]] || [[ $setting == "no" ]]; then
if [[ -n $stbd ]]; then
/usr/syno/bin/synosetkeyvalue "$synoinfo" "$stbd" yes
/usr/syno/bin/synosetkeyvalue "$synoinfo2" "$stbd" yes
enabled="yes"
fi
elif [[ $setting == "yes" ]]; then
echo -e "\nTiny Btrfs Data Deduplication already enabled."
fi
# Disable support_btrfs_dedupe
if [[ $enabled == "yes" ]]; then
if grep "$sbd" "$synoinfo" >/dev/null; then
/usr/syno/bin/synosetkeyvalue "$synoinfo" "$sbd" no
fi
if grep "$sbd" "$synoinfo2" >/dev/null; then
/usr/syno/bin/synosetkeyvalue "$synoinfo2" "$sbd" no
fi
fi
fi
# Check if we enabled deduplication
setting="$(/usr/syno/bin/synogetkeyvalue "$synoinfo" ${sbd})"
setting2="$(/usr/syno/bin/synogetkeyvalue "$synoinfo" ${stbd})"
if [[ $enabled == "yes" ]]; then
if [[ $tiny != "yes" ]]; then
if [[ $setting == "yes" ]]; then
echo -e "\nEnabled Btrfs Data Deduplication."
reload="yes"
else
ding
echo -e "\n${Error}ERROR${Off} Failed to enable Btrfs Data Deduplication!"
fi
else
if [[ $setting2 == "yes" ]]; then
echo -e "\nEnabled Tiny Btrfs Data Deduplication."
reload="yes"
else
ding
echo -e "\n${Error}ERROR${Off} Failed to enable Tiny Btrfs Data Deduplication!"
fi
fi
fi
#------------------------------------------------------------------------------
# Edit /var/packages/StorageManager/target/ui/storage_panel.js
# Enable dedupe config button for HDDs in DSM 7.2.1
if [[ -f "$strgmgr" ]] && [[ $hdd == "yes" ]]; then
# StorageManager package is installed
if grep '&&e.dedup_info.show_config_btn' "$strgmgr" >/dev/null; then
# Backup storage_panel.js"
storagemgrver="$(synopkg version StorageManager)"
echo ""
if [[ ! -f "${strgmgr}.$storagemgrver" ]]; then
if cp -p "$strgmgr" "${strgmgr}.$storagemgrver"; then
echo -e "Backed up $(basename -- "$strgmgr")"
else
ding
echo -e "${Error}ERROR${Off} Failed to backup $(basename -- "$strgmgr")!"
fi
fi
sed -i 's/&&e.dedup_info.show_config_btn//g' "$strgmgr"
# Check if we edited file
if ! grep '&&e.dedup_info.show_config_btn' "$strgmgr" >/dev/null; then
echo -e "Enabled dedupe config menu for HDDs and 2.5\" SSDs."
reload="yes"
else
ding
echo -e "${Error}ERROR${Off} Failed to enable dedupe config menu for HDDs and 2.5\" SSDs!"
fi
else
echo -e "\nDedupe config menu for HDDs and 2.5\" SSDs already enabled."
fi
fi
#----------------------------------------------------------
# Finished
if [[ $reboot == "yes" ]]; then
rebootmsg
elif [[ $reload == "yes" ]]; then
reloadmsg
else
echo -e "\nFinished"
fi
exit