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/conf/systemd/samba-util.sh
#! /bin/bash
#
# util functions for samba's usage

# source guard
[[ "${_SOURCE_GUARD_SYNOSAMBA_SAMBA_UTIL}" != "yes" ]] || return
_SOURCE_GUARD_SYNOSAMBA_SAMBA_UTIL="yes"

DOMAIN_DB_VERSION=11
SAMBA_ROOT="/var/packages/SMBService"
SAMBA_BIN="$(/bin/realpath ${SAMBA_ROOT}/target/usr/bin)"
SAMBA_SBIN="$(/bin/realpath ${SAMBA_ROOT}/target/usr/sbin)"
SYNOSYSTEMCTL="/usr/syno/bin/synosystemctl"
SYNOACLTOOL="/usr/syno/bin/synoacltool"
SYNOGETKEYVALUE="/usr/syno/bin/synogetkeyvalue"

# basic util functions
syslog() { # logger args
	local ret=$?
	/bin/logger -p user.err -t "$(basename "$0")($$)" "$@"
	return $ret
}

message() { # echo args
	local ret=$?
	echo "$@"
	return $ret
} >&2

warn() { # echo args
	local ret=$?
	local H="" E=""
	echo -en "$H$*" ; echo "$E"
	return $ret
} >&2

is_any_running() {
	local i=
	for i in "$@"; do
		if /bin/pidof "$i" >/dev/null; then
			return 0
		fi
	done
	return 1
}

is_ad_mode() {
	if [ -f "/run/samba/synoadserver" ]; then
		return 0;
	fi
	return 1;
}

is_domain_mode()
{
	local SECURITY
	SECURITY=$(${SYNOGETKEYVALUE} /etc/samba/smb.conf "security")
	if [ "ads" == "$SECURITY" ] || [ "domain" == "$SECURITY" ]; then
		exit 0;
	fi
	if is_ad_mode; then
		exit 0;
	fi
	exit 1;
}

is_enabled() { # <pkg-synosamba-smbd | pkg-synosamba-nmbd | pkg-synosamba-winbindd>
	[[ "enabled" == $(${SYNOSYSTEMCTL} get-enable-status "$1") ]]
}

is_active() { # <pkg-synosamba-smbd | pkg-synosamba-nmbd | pkg-synosamba-winbindd>
	[[ "active" == $(${SYNOSYSTEMCTL} get-active-status "$1") ]]
}

safe_restart() { # <pkg-synosamba-smbd | pkg-synosamba-nmbd | pkg-synosamba-winbindd>
	${SYNOSYSTEMCTL} try-restart "$@" >/dev/null 2>&1
}

safe_restart_noblock() { # <pkg-synosamba-smbd | pkg-synosamba-nmbd | pkg-synosamba-winbindd>
	${SYNOSYSTEMCTL} try-restart --no-block "$@" >/dev/null 2>&1
}

safe_reload() { # <pkg-synosamba-smbd | pkg-synosamba-nmbd | pkg-synosamba-winbindd>
	for process_name in "$@"; do
		if is_active "${process_name}"; then
			${SYNOSYSTEMCTL} reload "${process_name}" >/dev/null 2>&1
		fi
	done
}

safe_reload_noblock() { # <pkg-synosamba-smbd | pkg-synosamba-nmbd | pkg-synosamba-winbindd>
	for process_name in "$@"; do
		if is_active "${process_name}"; then
			${SYNOSYSTEMCTL} reload --no-block "${process_name}" >/dev/null 2>&1
		fi
	done
}

smb_status() { # <pkg-synosamba-smbd | pkg-synosamba-nmbd | pkg-synosamba-winbindd>
	/bin/systemctl status "$@" 2>&1
}

# smb util functions
file_size() {
	local File="$1"
	local size=0
	if [ -f "$1" ]; then
		size=$(${SYNOACLTOOL} -stat "$File" | /bin/grep "File size:" | /bin/awk '{ print $3;}')
	fi
	echo "$size"
}

ARRAY_INSTALL_PATH=(
"/var/cache/samba" "755"   #no this directory will let smbd start fail
"/var/log/samba" "755"     #no this directory will let smbd log to stdout
"/etc/samba/private" "755" #no this directory will open/create secrets.tdb fail and force smb_panic
)
install_dir_recover() {
	local count=0
	while [ -n "${ARRAY_INSTALL_PATH[$count]}" ];
	do
		local dir_path="${ARRAY_INSTALL_PATH[$count]}"
		local mode="${ARRAY_INSTALL_PATH[$((count+1))]}"
		if [ ! -d "$dir_path" ]; then
			syslog "$dir_path not exist. create it."
			/bin/install -d -m "$mode" "$dir_path"
		fi
		count=$((count+2))
	done
}

# below path will create by smbd/nmbd/winbindd. But if dir exist with wrong perm, the daemon will start fail.
ARRAY_PERM_PATH=(
"/run/samba/ncalrpc/np" "700"
"/run/samba/ncalrpc" "755"
"/run/samba/msg.lock" "755"
"/run/samba/msg.sock" "700"
"/run/samba/winbindd" "755"
"/run/samba/nmbd" "755"
"/var/lib/samba/winbindd_privileged" "750"
)
perm_recover() {
	local count=0
	local st_mode
	while [ -n "${ARRAY_PERM_PATH[$count]}" ];
	do
		local target_path="${ARRAY_PERM_PATH[$count]}"
		local mode="${ARRAY_PERM_PATH[$((count+1))]}"
		if [ -e "$target_path" ]; then
			st_mode=$(/bin/stat -c "%a" "$target_path")
			if [ "$st_mode" != "$mode" ]; then
				syslog "$dir_path wrong mode $st_mode. correct to $mode."
				/bin/chmod "$mode" "$target_path"
			fi
		fi
		count=$((count+2))
	done
}

samba_file_dir_check() {
	# install path check and recover
	install_dir_recover

	# samba create path check permission
	perm_recover

	#check smb.conf
	local smbconfsize
	smbconfsize=$(file_size /etc/samba/smb.conf)
	if [ "$smbconfsize" = 0 ]; then
		syslog "/etc/samba/smb.conf is empty or not exist. Recover by /etc.defaults/samba/smb.conf"
		/bin/mv /etc/samba/smb.conf /etc/samba/smb.conf.bad > /dev/null 2>&1
		/bin/cp -f /etc.defaults/samba/smb.conf /etc/samba/smb.conf
	fi
}

smb_remove_share_tdbs() {
	# those tdb will be used by nmbd, smbd, winbindd
	/bin/rm -f /run/samba/messages.tdb /run/samba/serverid.tdb
}

smb_remove_smbd_temp_tdbs() {
	/bin/rm -f /run/samba/brlock.tdb /run/samba/connections.tdb \
		/run/samba/login_cache.tdb "/var/cache/samba/printing/*.tdb" \
		/run/samba/sessionid.tdb /run/samba/locking.tdb \
		/run/samba/unexpected.tdb /run/samba/deferred_open.tdb \
		/var/cache/samba/notify_onelevel.tdb
}

smb_remove_winbindd_temp_tdbs()
{
	#We default enable winbindd offline logon
	#so we cannot remove winbindd_cache.tdb when restart winbindd.
	#The netsamlogon_cache.tdb may be cannot be delete for auth.
	#But netsamlogon_cache.tdb has too much cache issue.

	local cache_size=0
	if [ ! -f /var/lib/samba/winbindd_cache.tdb ]; then
		return
	fi

	#winbind_cache.tdb too large will cause the winbindd check very long time
	#If size > 200MB(200*1024*1024 = 209715200 Byte), we need delete it to keep performance
	cache_size=$(file_size /var/lib/samba/winbindd_cache.tdb)
	if [ "$cache_size" != "" ] &&  [ "$cache_size" -gt 209715200 ]; then
		#when cache size too large, we should clear it before starting winbindd
		/bin/rm -f "$(/usr/bin/realpath /var/lib/samba/winbindd_cache.tdb)"
	fi
	/bin/rm -f /var/cache/samba/winbindd_cache.tdb* /var/lib/samba/winbindd_cache.tdb*
}

smb_remove_smbd_winbindd_share_tdbs() {
	if is_any_running smbd winbindd; then
		return 1
	fi
	/bin/rm -f /var/cache/samba/netsamlogon_cache.tdb /run/samba/gencache_notrans.tdb \
		  /run/samba/gencache.tdb /var/lib/samba/group_mapping.tdb
}

smb_remove_temp_tdbs() { # <void>
	if is_any_running smbd nmbd winbindd; then
		return 1
	fi

	message "remove temp tdbs"

	smb_remove_smbd_temp_tdbs
	smb_remove_winbindd_temp_tdbs
	smb_remove_smbd_winbindd_share_tdbs
	smb_remove_share_tdbs
}

smb_check_tdb() { # <tdb file>
	local tdbfile=${1:?"error param"}
	local backup=${SAMBA_BIN}/tdbbackup

	message -n "check tdb: $tdbfile ... "

	if [ -f "$tdbfile" ]; then
		if $backup -v "$tdbfile" >/dev/null 2>&1; then
			# tdb is good make another backup
			/bin/mv -f "$tdbfile.bkp" "$tdbfile.bkp.old"
			if $backup -s ".bkp" "$tdbfile" >/dev/null 2>&1; then
				message "done"
				/bin/rm -f "$tdbfile.bkp.old"
			else
				warn "backup failed"
				/bin/mv -f "$tdbfile.bkp.old" "$tdbfile.bkp"
			fi
		elif [ -f "$tdbfile.bkp" ]; then
			warn "corrupt, restore"
			if ! $backup -v -s ".bkp" "$tdbfile" >/dev/null; then
				warn "restore failed, remove it"
				/bin/rm -f "$tdbfile"
			fi
		else
			warn "corrupt, remove it"
			/bin/rm -f "$tdbfile"
		fi
	elif [ -f "$tdbfile.bkp" ];then
		warn "lost, use backup tdb"
		if ! $backup -v -s ".bkp" "$tdbfile" > /dev/null; then
			warn "restore failed"
		fi
	else
		message "not exist"
	fi

	return 0
}

# first param is /volumeX
is_winbindd_db_in_volume() {
	local -r volume=$1
	local -r winbindd_db_path=(
		/var/lib/samba/winbindd_cache.tdb
		/usr/syno/etc/private/.db.domain_user_full
		/usr/syno/etc/private/.db.domain_group_full
	)

	if [[ "$volume" != "/volume"* ]]; then
		return 1
	fi

	for path in ${winbindd_db_path[*]}; do
		if [[ $(readlink "$path") == "$volume/"* ]]; then
			return 0
		fi
	done
	return 1
}

is_need_reload_smbd() {
	local -r enable_multichannel=$("${SAMBA_BIN}"/testparm -s \
		--parameter-name="server multi channel support" 2>/dev/null)
	local -r enable_smb_autoblock=$("${SAMBA_BIN}"/testparm -s \
		--parameter-name="syno autoblock support" 2>/dev/null)

	if [[ "${enable_multichannel,,}" == "yes" ]]; then
		return 0
	fi

	if [[ "${enable_smb_autoblock,,}" == "yes" ]]; then
		return 0
	fi

	return 1
}

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
	cmd="$1"
	arg_type=$(type -t "$cmd")
	shift
	if [[ "${arg_type}" != "function" ]] || [[ "${cmd}" == _* ]]; then
		message "$0: Invalid argument: $1"
		exit 1
	fi
	${cmd} "$@"
fi

# vim:set noexpandtab: