File: //var/packages/SMBService/scripts/updater.sh
#!/bin/bash
# source guard
[[ "${_SOURCE_GUARD_SYNOSAMBA_UPDATER}" != "yes" ]] || return
_SOURCE_GUARD_SYNOSAMBA_UPDATER="yes"
# shellcheck source=package/scripts/util.sh
source "/var/packages/SMBService/scripts/util.sh"
_remove_conflict_nbt_sid_with_ldap_from_secrets_tdb()
{
local -r TESTPARM="${SYNOPKG_PKGDEST}/usr/bin/testparm"
local -r TDBBACKUP="${SYNOPKG_PKGDEST}/usr/bin/tdbbackup"
local -r TDBDUMP="${SYNOPKG_PKGDEST}/usr/bin/tdbdump"
local -r TDBTOOL="${SYNOPKG_PKGDEST}/usr/bin/tdbtool"
local -r secrets_tdb="/etc/samba/private/secrets.tdb"
if [[ ! -f "${secrets_tdb}" ]]; then
echo "${secrets_tdb} does not exist, skip"
return
fi
if [[ ! -e /usr/syno/etc/ldapclient/ldap_joined ]]; then
echo "Not join ldap, skip"
return
fi
local -r ldap_domain=$(${TESTPARM} -s --parameter-name="syno ldap domain" 2>/dev/null)
local -r host_name=$(hostname)
local -r removed_key="SECRETS/SID/${host_name^^}"
if [[ "${ldap_domain,,}" != "${host_name,,}" ]]; then
echo "${ldap_domain,,} and ${host_name,,} does not equal, skip"
return
fi
if ! ${TDBDUMP} -k "${removed_key}" "${secrets_tdb}" >/dev/null 2>&1; then
echo "${secrets_tdb} does not have ${removed_key}, skip."
return
fi
${TDBBACKUP} "${secrets_tdb}" -s ".bak"
echo "remove '${removed_key}' from ${secrets_tdb}"
${TDBTOOL} "${secrets_tdb}" delete "${removed_key}"
}
_remove_domain_img_cache()
{
local IMGLINK="/usr/syno/etc/private/.account.cache.img"
local IMGPATH=""
IMGPATH="$(realpath $IMGLINK)"
if [ -f "$IMGPATH" ]; then
/usr/bin/systemctl stop accountdb-cache
rm "$IMGPATH"
if [[ "enabled" == $(/usr/syno/bin/synosystemctl get-enable-status "accountdb-cache") ]]; then
/usr/bin/systemctl start accountdb-cache
fi
fi
}
_is_broken_durable_handles_option()
{
local -r smbinfo_conf="/etc/samba/smbinfo.conf"
local -r durable_handles_config_val=$(
${SYNOGETKEYVALUE} "${smbinfo_conf}" "durable handles"
)
local -A durable_handles_config_map=()
case "${durable_handles_config_val,,}" in
"yes")
durable_handles_config_map["posix locking"]="no"
durable_handles_config_map["kernel share modes"]="no"
;;
"no")
durable_handles_config_map["posix locking"]="yes"
durable_handles_config_map["kernel share modes"]="yes"
;;
"")
durable_handles_config_map["posix locking"]=""
durable_handles_config_map["kernel share modes"]=""
;;
*)
# unexpected, treat as broken and reset anyway
return 0
;;
esac
local config_value
local expected_value
for config in "${!durable_handles_config_map[@]}"; do
config_value=$(${SYNOGETKEYVALUE} "${smbinfo_conf}" "${config}")
expected_value=${durable_handles_config_map[${config}]}
if [[ "${config_value,,}" != "${expected_value,,}" ]]; then
return 0
fi
done
return 1
}
_fix_durable_handles()
{
local -r smbinfo_conf="/etc/samba/smbinfo.conf"
if ! _is_broken_durable_handles_option; then
return
fi
if is_smb_option_enabled "durable handles"; then
_setkeyvalue_noquote "${smbinfo_conf}" "durable handles" "yes"
_setkeyvalue_noquote "${smbinfo_conf}" "posix locking" "no"
_setkeyvalue_noquote "${smbinfo_conf}" "kernel share modes" "no"
else
remove_option_from_file "${smbinfo_conf}" "durable handles"
remove_option_from_file "${smbinfo_conf}" "posix locking"
remove_option_from_file "${smbinfo_conf}" "kernel share modes"
fi
logger_info "durable handles config option fixed"
}
_enable_durable_handles_if_smb_tm_enabled()
{
local -r smbinfo_conf="/etc/samba/smbinfo.conf"
if is_smb_option_enabled "durable handles"; then
return
fi
local -r smb_time_machine=$(
/usr/syno/bin/synosdutils time-machine --smb-status | \
awk -F ': ' '{ print $2 }'
)
if [[ "${smb_time_machine,,}" != "enable"* ]]; then
return
fi
_setkeyvalue_noquote "${smbinfo_conf}" "durable handles" "yes"
_setkeyvalue_noquote "${smbinfo_conf}" "posix locking" "no"
_setkeyvalue_noquote "${smbinfo_conf}" "kernel share modes" "no"
logger_info "durable handles enabled"
}
_remove_old_smb_db()
{
local -r db_list=(
"/var/cache/samba/leases.tdb"
"/var/cache/samba/smbprofile.tdb"
)
for db in "${db_list[@]}"; do
rm -f "${db}"
done
}
_has_homes_share()
{
if /usr/syno/sbin/synoshare --get "homes" >/dev/null 2>&1; then
return 0
fi
return 1
}
_is_fresh_install_DSM722_or_later()
{
local -r DSM_VERSION=$(${SYNOGETKEYVALUE} /etc.defaults/VERSION buildnumber)
if [[ "${DSM_VERSION}" -lt "72787" ]] || [[ -e /.old_patch_info/VERSION ]]; then
return 1
fi
return 0
}
_enable_directory_leasing_home_only()
{
if ! is_smb_option_enabled "oplocks"; then
return
fi
# Enable directory leasing home only if one of the following conditions is met:
# - user does not have "homes" share
# This is because we don't want to change the behavior of existing homes.
# - fresh install DSM 7.2.2 or later
if _has_homes_share && ! _is_fresh_install_DSM722_or_later; then
return
fi
smb_enable_directory_leasing_home_only
logger_info "[Directory Leasing] enabled and apply to homes and home only"
}
_update() {
local -r pkgver_old=${1?"Invalid old package version"}
local -r pkgver_target=${2?"Invalid target package version"}
local -r update_func=${3?"Invalid update function"}
if [[ "$((10#${pkgver_old/*-/}))" -ge "$((10#${pkgver_target}))" ]];then
return
fi
logger_info "Execute version ${pkgver_target} updater '${update_func}'"
${update_func}
}
# Update only when the major version is the same
_update_by_version() {
local -r pkgver_old=${1?"Invalid old package version"}
local -r pkgver_target=${2?"Invalid target package version"}
local -r update_func=${3?"Invalid update function"}
if [[ "$((10#${pkgver_old/*-/}))" -ne "$((10#${pkgver_target}))" ]]; then
return
fi
logger_info "Execute version ${pkgver_target} updater '${update_func}'"
${update_func}
}
updater() {
local -r pkgver_old=${1?"Invalid old package version"}
logger_info "updater: upgrade from ${pkgver_old}"
_update "${pkgver_old}" "0407" \
_remove_conflict_nbt_sid_with_ldap_from_secrets_tdb
_update "${pkgver_old}" "0433" \
_remove_domain_img_cache
_update "${pkgver_old}" "0866" \
_fix_durable_handles
_update "${pkgver_old}" "0866" \
_enable_durable_handles_if_smb_tm_enabled
_update "${pkgver_old}" "2303" \
_remove_old_smb_db
_update "${pkgver_old}" "2310" \
_enable_directory_leasing_home_only
_update_by_version "${pkgver_old}" "3041" \
_remove_domain_img_cache
}
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
cmd="$1"
arg_type=$(type -t "$cmd")
shift
if [[ "${arg_type}" != "function" ]] || [[ "${cmd}" == _* ]]; then
logger_info "$0: Invalid argument: $1"
exit 1
fi
${cmd} "$@"
fi
# vim:set ts=4 sw=4 sts=4 expandtab: