File: //usr/syno/sbin/synoupgradepreserve_for_configs.sh
#!/bin/sh
PreservedFileForConfigsDir="/usr/syno/synoinstall/space-preserve-for-configs"
PreservedFilePrefix="temp-config"
PreservedFileNum=100
PreservedDirSizeInKB=0 # there are no valid estimation of dir size on btrfs root
PreservedFileSizeInKB=100
PreservedFileTotalSizeInKB=$(( PreservedFileNum*PreservedFileSizeInKB + PreservedDirSizeInKB ))
MarginSizeInKB=$(( 100*1024 )) # 100 MB
Help() {
cat << EOF
usage: $0 options rootMnt
--ensure ensure the preserved space on rootMnt.
should not use this option in junior mode.
--cleanup cleanup the preserved space on rootMnt.
--help print this.
EOF
return 0
}
ErrorLog() {
/bin/logger -p "error" -s -t "$0" "$@"
}
GetAvailSizeInKB() {
local rootMnt=$1
local avail_block_num
if ! avail_block_num=$(/bin/stat -f "$rootMnt" -c "%a"); then
ErrorLog "Failed to get available block num on $rootMnt"
return 1
fi
local block_size
if ! block_size=$(/bin/stat -f "$rootMnt" -c "%S"); then
ErrorLog "Failed to get block size on $rootMnt"
return 1
fi
local avail_size
avail_size=$(( avail_block_num*block_size/1024 )) # from B to KB
/bin/echo "$avail_size"
}
GetSizeInKB() {
local path="$1"
local size=0
if [ -e "$path" ]; then
local stat_result
if ! stat_result=$(/bin/find "$path" -print0 | /bin/xargs -0 -I{} /bin/stat -c %s {}); then
ErrorLog "Failed to find all files and calculate size"
return 1
fi
# NOTE: "/bin/awk" is not in junior mode
if ! size=$(/bin/echo "$stat_result" | /bin/awk '{sum += $1} END {print sum}'); then
ErrorLog "Failed to sum up size"
return 1
fi
fi
/bin/echo "$((size / 1024))"
}
RemoveFiles() {
if ! /bin/rm -rf "$1"; then
ErrorLog "Failed to remove files"
return 1
fi
}
CheckExistBackingFiles() {
local path="$1"; shift
if [ ! -d "$path" ]; then
ErrorLog "dir is not exist [$path]"
return 1
fi
local size=0
if ! size=$(GetSizeInKB "$path"); then
ErrorLog "Failed to get size [$path]"
return 1
fi
[ "$PreservedFileTotalSizeInKB" -le "$size" ]
}
EnsureBackingFiles() {
local rootMnt="$1"
local path="$rootMnt$PreservedFileForConfigsDir"
if [ ! -x /bin/stat ] || [ ! -x /bin/awk ]; then
ErrorLog "There is no executable /bin/stat or /bin/awk. This option (\"--ensure\") should not be used in junior mode."
return 1
fi
if CheckExistBackingFiles "$path"; then
return 0
fi
RemoveFiles "$path"
local avail_size=0
if ! avail_size=$(GetAvailSizeInKB "$rootMnt"); then
ErrorLog "Failed to get available size"
return 1
fi
local guaranteed_size=$(( PreservedFileTotalSizeInKB + MarginSizeInKB ))
if [ "$avail_size" -lt "$guaranteed_size" ]; then
ErrorLog "No enough space left on \"$rootMnt\" [$avail_size, $guaranteed_size]"
return 1
fi
if ! /bin/mkdir -p "$path"; then
ErrorLog "Failed to create dir [$path]"
return 1
fi
for i in $(/bin/seq 1 "$PreservedFileNum"); do
local file="$path/$PreservedFilePrefix-$i"
/bin/dd if=/dev/zero of="$file" bs="1K" count="$PreservedFileSizeInKB" status=none
done
if ! CheckExistBackingFiles "$path"; then
ErrorLog "Failed to dd files for preserved space [$path]"
return 1
fi
return 0
}
CleanBackingFiles() {
local rootMnt="$1"; shift
if ! RemoveFiles "$rootMnt$PreservedFileForConfigsDir"; then
ErrorLog "Failed to clean backing files"
return 1
fi
}
main() {
local action="$1"; shift
local rootMnt="${1:-/}"; shift
case "$action" in
# NOTE: should not use --ensure in junior mode
--ensure)
if ! EnsureBackingFiles "$rootMnt"; then
ErrorLog "Failed to ensure preserved space"
CleanBackingFiles "$rootMnt"
return 1
fi
;;
--cleanup)
if ! CleanBackingFiles "$rootMnt"; then
ErrorLog "Failed to cleanup preserved space"
return 1
fi
;;
--help)
Help
;;
*)
ErrorLog "Invalid action; should be [--ensure|--cleanup|--help]"
return 1
esac
return 0
}
main "$@"