HEX
Server: Apache/2.4.63 (Unix)
System: Linux TOMS-220NAS 4.4.302+ #86009 SMP Wed Nov 26 18:19:17 CST 2025 x86_64
User: flavio87 (1026)
PHP: 8.3.27
Disabled: NONE
Upload Files
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: