#!/bin/bash # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Copyright 2018-2019 Alessandro "Locutus73" Miele # You can download the latest version of this script from: # https://github.com/MiSTer-devel/Scripts_MiSTer # Changelog: # Version 2.2.1 - 2026-04-30 - Skips already-mounted targets, tries DNS before NetBIOS, logs boot starts, # and recovers stale /tmp/cifs_mount mounts before remounting. # - Waits for a default route at boot, settles dual-interface routing, # and can restart NTP after successful boot mounts. # Version 2.2.0 - 2026-04-19 - MiSTer-safe boot automount: MOUNT_AT_BOOT now uses /media/fat/linux/user-startup.sh when available, # with a late /etc/init.d fallback, instead of /etc/network/if-up.d hooks. # - Removes legacy CIFS network hooks before config validation so old hooks do not keep breaking WiFi. # - Waits for IPv4 before boot mounting, adds bounded network/server waits, and fails cleanly on lookup timeout. # - Preserves SHARE_DIRECTORY support and fixes failed single-directory mounts reporting success. # Version 2.1.1 - 2023-11-16 - Updated Github link, fixed unary operator error if "SHARE_DIRECTORY" not specified. # Version 2.1.0 - 2022-04-16 - Introduced "SHARE_DIRECTORY" option; useful if you don't have a dedicated MiSTer-share on the remote server, but only a specific folder which should be mounted here. # Version 2.0.1 - 2019-05-06 - Removed kernel modules downloading, now the script asks to update the MiSTer Linux system when necessary. # Version 2.0 - 2019-02-05 - Renamed from mount_cifs.sh and umount_cifs.sh to cifs_mount.sh and cifs_umount.sh for having them sequentially listed in alphabetical order. # Version 1.8 - 2019-02-03 - Added MOUNT_AT_BOOT option: "true" for automounting CIFS shares at boot time; it will create start/kill scripts in /etc/network/if-up.d and /etc/network/if-down.d. # Version 1.7 - 2019-02-02 - The script temporarily modifies the firewalling rules for querying the CIFS Server name with NetBIOS when needed. # Version 1.6 - 2019-02-02 - The script tries to download kernel modules (when needed) using SSL certificate verification. # Version 1.5.1 - 2019-01-19 - Now the script checks if kernel modules are built in, so it's compatible with latest MiSTer Linux distros. # Version 1.5 - 2019-01-15 - Added WAIT_FOR_SERVER option; set it to "true" in order to wait for the CIFS server to be reachable; useful when using this script at boot time. # Version 1.4 - 2019-01-07 - Added support for an ini configuration file with the same name as the original script, i.e. mount_cifs.ini; changed LOCAL_DIR="*" behaviour so that, when SINGLE_CIFS_CONNECTION="true", all remote directories are listed and mounted locally; kernel modules moved to /media/fat/linux. # Version 1.3 - 2019-01-05 - Added an advanced SINGLE_CIFS_CONNECTION option for making a single CIFS connection to the CIFS server, you can leave it set to "true"; implemented LOCAL_DIR="*" for mounting all local directories on the SD root. # Version 1.2 - 2019-01-04 - Changed the internal field separator from space " " to pipe "|" in order to allow directory names with spaces; made the script verbose with some output. # Version 1.1.1 - 2019-01-03 - Improved server name resolution speed for multiple mount points; now you can directly use an IP address; added des_generic.ko fscache.ko kernel modules. # Version 1.1 - 2019-01-03 - Implemented multiple mount points, improved descriptions for user options. # Version 1.0.1 - 2018-12-22 - Changed some option descriptions, thanks NML32 # Version 1.0 - 2018-12-20 - First commit #========= USER OPTIONS ========= #You can edit these user options or make an ini file with the same #name as the script, i.e. cifs_mount.ini, containing the same options. #Your CIFS Server, i.e. your NAS name or its IP address. SERVER="" #The share name on the Server. SHARE="MiSTer" #Use this if only a specific directory from the share's root should be mounted. SHARE_DIRECTORY="" #The user name, leave blank for guest access. USERNAME="" #The user password, irrelevant (leave blank) for guest access. PASSWORD="" #Optional user domain, when in doubt leave blank. DOMAIN="" #Local directory/directories where the share will be mounted. #- It can ba a single directory, i.e. "cifs", so the remote share, i.e. \\NAS\MiSTer # will be directly mounted on /media/fat/cifs (/media/fat is the root of the SD card). # NOTE: /media/fat/cifs is a special location that the mister binary will try before looking in # the standard games location of /media/fat/games, so "cifs" is the suggested setting. #- It can be a pipe "|" separated list of directories, i.e. "Amiga|C64|NES|SNES", # so the share subdirectiories with those names, # i.e. \\NAS\MiSTer\Amiga, \\NAS\MiSTer\C64, \\NAS\MiSTer\NES and \\NAS\MiSTer\SNES # will be mounted on local /media/fat/Amiga, /media/fat/C64, /media/fat/NES and /media/fat/SNES. #- It can be an asterisk "*": when SINGLE_CIFS_CONNECTION="true", # all the directories in the remote share will be listed and mounted locally, # except the special ones (i.e. linux and config); # when SINGLE_CIFS_CONNECTION="false" all the directories in the SD root, # except the special ones (i.e. linux and config), will be mounted when one # with a matching name is found on the remote share. LOCAL_DIR="cifs" #Optional additional mount options, when in doubt leave blank. #If you have problems not related to username/password, you can try "vers=2.0" or "vers=3.0". ADDITIONAL_MOUNT_OPTIONS="" #"true" in order to wait for the CIFS server to be reachable; #useful when using this script at boot time. WAIT_FOR_SERVER="false" #"true" for automounting CIFS shares at boot time; #this MiSTer-safe copy uses /media/fat/linux/user-startup.sh when available, #and falls back to a late /etc/init.d startup entry instead of network if-up.d hooks. MOUNT_AT_BOOT="false" #========= ADVANCED OPTIONS ========= BASE_PATH="/media/fat" #MISTER_CIFS_URL="https://github.com/MiSTer-devel/CIFS_MiSTer" KERNEL_MODULES="md4.ko|md5.ko|des_generic.ko|fscache.ko|cifs.ko" IFS="|" SINGLE_CIFS_CONNECTION="true" #Pipe "|" separated list of directories which will never be mounted when LOCAL_DIR="*" SPECIAL_DIRECTORIES="config|linux|System Volume Information" BOOT_START_DELAY_SECONDS="8" NETWORK_READY_TIMEOUT_SECONDS="45" DEFAULT_ROUTE_READY_TIMEOUT_SECONDS="30" DUAL_INTERFACE_SETTLE_SECONDS="5" SERVER_WAIT_TIMEOUT_SECONDS="60" BOOT_LOG_PATH="/tmp/cifs_mount.log" RESTART_NTP_AFTER_BOOT_MOUNT="auto" NTP_INIT_SCRIPT="/etc/init.d/S49ntp" #=========CODE STARTS HERE========= BOOT_ARG="--boot-start" USER_STARTUP="/media/fat/linux/user-startup.sh" USER_STARTUP_TEMPLATE="/media/fat/linux/_user-startup.sh" trim_ini_field() { local FIELD="$1" FIELD="${FIELD#"${FIELD%%[!$' \t']*}"}" FIELD="${FIELD%"${FIELD##*[!$' \t']}"}" printf '%s' "$FIELD" } load_cifs_ini() { local INI_FILE="$1" local LINE KEY VALUE ALLOWED_KEY KEY_ALLOWED shift while IFS= read -r LINE || [ "$LINE" != "" ] do LINE=${LINE%$'\r'} case "$LINE" in *=*) ;; *) continue ;; esac KEY=$(trim_ini_field "${LINE%%=*}") case "$KEY" in ''|\#*) continue ;; esac KEY_ALLOWED="false" for ALLOWED_KEY in "$@" do if [ "$KEY" == "$ALLOWED_KEY" ] then KEY_ALLOWED="true" break fi done [ "$KEY_ALLOWED" == "true" ] || continue VALUE=$(trim_ini_field "${LINE#*=}") case "$VALUE" in \"*) VALUE=${VALUE#\"}; VALUE=${VALUE%%\"*} ;; \'*) VALUE=${VALUE#\'}; VALUE=${VALUE%%\'*} ;; esac printf -v "$KEY" '%s' "$VALUE" done < "$INI_FILE" } resolve_path() { if command -v realpath >/dev/null 2>&1 then realpath "$1" 2>/dev/null && return 0 fi if command -v readlink >/dev/null 2>&1 then readlink -f "$1" 2>/dev/null && return 0 fi echo "$1" } ORIGINAL_SCRIPT_PATH="$0" if [ "$ORIGINAL_SCRIPT_PATH" == "bash" ] then ORIGINAL_SCRIPT_PATH=$(ps | grep "^ *$PPID " | grep -o "[^ ]*$") fi SCRIPT_NAME=${ORIGINAL_SCRIPT_PATH##*/} SCRIPT_NAME=${SCRIPT_NAME%.*} SCRIPT_REALPATH=$(resolve_path "$ORIGINAL_SCRIPT_PATH") CIFS_MOUNT_INI_KEYS=( SERVER SHARE SHARE_DIRECTORY USERNAME PASSWORD DOMAIN LOCAL_DIR ADDITIONAL_MOUNT_OPTIONS WAIT_FOR_SERVER MOUNT_AT_BOOT BASE_PATH KERNEL_MODULES SINGLE_CIFS_CONNECTION SPECIAL_DIRECTORIES BOOT_START_DELAY_SECONDS NETWORK_READY_TIMEOUT_SECONDS DEFAULT_ROUTE_READY_TIMEOUT_SECONDS DUAL_INTERFACE_SETTLE_SECONDS SERVER_WAIT_TIMEOUT_SECONDS BOOT_LOG_PATH RESTART_NTP_AFTER_BOOT_MOUNT NTP_INIT_SCRIPT ) INI_PATH=${ORIGINAL_SCRIPT_PATH%.*}.ini FALLBACK_INI="/media/fat/Scripts/cifs_mount.ini" STARTUP_LEGACY_MARKER="# Startup ${SCRIPT_NAME}" STARTUP_BEGIN_MARKER="# ${SCRIPT_NAME}: BEGIN managed boot mount" STARTUP_END_MARKER="# ${SCRIPT_NAME}: END managed boot mount" STARTUP_MATCH="${SCRIPT_NAME}.sh ${BOOT_ARG}" STARTUP_COMMAND="[ -e \"${SCRIPT_REALPATH}\" ] && \"${SCRIPT_REALPATH}\" ${BOOT_ARG} &" INIT_SERVICE_PATH="/etc/init.d/S99${SCRIPT_NAME}" BOOT_CONFIG_CHANGED="false" ROOT_WAS_RO="false" ROOT_EDIT_ACTIVE="false" IPTABLES_SUPPORT="false" FIREWALL_RULE_ADDED="false" MOUNT_FAILURES=0 MULTI_INTERFACE_BOOT="false" BOOT_START="false" if [ "${1:-}" == "$BOOT_ARG" ] then BOOT_START="true" shift fi if [ -f "$INI_PATH" ] then load_cifs_ini "$INI_PATH" "${CIFS_MOUNT_INI_KEYS[@]}" elif [ "$INI_PATH" != "$FALLBACK_INI" ] && [ -f "$FALLBACK_INI" ] then load_cifs_ini "$FALLBACK_INI" "${CIFS_MOUNT_INI_KEYS[@]}" fi start_boot_log() { [ "$BOOT_START" == "true" ] || return 0 : >> "$BOOT_LOG_PATH" 2>/dev/null || return 0 echo "==== $(date '+%Y-%m-%d %H:%M:%S') ${SCRIPT_NAME} boot start ====" >> "$BOOT_LOG_PATH" exec >> "$BOOT_LOG_PATH" 2>&1 } start_boot_log begin_root_edit() { ROOT_WAS_RO="false" ROOT_EDIT_ACTIVE="true" if mount | grep "on / .*[(,]ro[,$]" -q then ROOT_WAS_RO="true" mount / -o remount,rw || return 1 fi } end_root_edit() { [ "$ROOT_EDIT_ACTIVE" == "true" ] || return 0 sync [ "${ROOT_WAS_RO:-false}" == "true" ] && mount / -o remount,ro ROOT_WAS_RO="false" ROOT_EDIT_ACTIVE="false" } open_netbios_lookup() { IPTABLES_SUPPORT="false" FIREWALL_RULE_ADDED="false" iptables -L >/dev/null 2>&1 || return 0 IPTABLES_SUPPORT="true" iptables -C INPUT -p udp --sport 137 -j ACCEPT >/dev/null 2>&1 && return 0 iptables -I INPUT -p udp --sport 137 -j ACCEPT >/dev/null 2>&1 && FIREWALL_RULE_ADDED="true" } close_netbios_lookup() { if [ "$IPTABLES_SUPPORT" == "true" ] && [ "$FIREWALL_RULE_ADDED" == "true" ] then iptables -D INPUT -p udp --sport 137 -j ACCEPT >/dev/null 2>&1 || true fi FIREWALL_RULE_ADDED="false" } is_ipv4_literal() { echo "$1" | grep -q "^[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}$" } resolve_dns_server() { local LOOKUP_SERVER="$1" local RESOLVED_SERVER if command -v getent >/dev/null 2>&1 then RESOLVED_SERVER=$(getent ahostsv4 "$LOOKUP_SERVER" 2>/dev/null | awk '/^[0-9]+\./ { print $1; exit }') [ "$RESOLVED_SERVER" != "" ] && echo "$RESOLVED_SERVER" && return 0 RESOLVED_SERVER=$(getent hosts "$LOOKUP_SERVER" 2>/dev/null | awk '/^[0-9]+\./ { print $1; exit }') [ "$RESOLVED_SERVER" != "" ] && echo "$RESOLVED_SERVER" && return 0 fi if command -v nslookup >/dev/null 2>&1 then RESOLVED_SERVER=$(nslookup "$LOOKUP_SERVER" 2>/dev/null | awk ' /^Name:/ || /Non-authoritative answer:/ { found = 1; next } found { for (i = 1; i <= NF; i++) { if ($i ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) { print $i exit } } } ') [ "$RESOLVED_SERVER" != "" ] && echo "$RESOLVED_SERVER" && return 0 fi return 1 } resolve_netbios_server() { local LOOKUP_SERVER="$1" local RESOLVED_SERVER command -v nmblookup >/dev/null 2>&1 || return 1 open_netbios_lookup RESOLVED_SERVER=$(nmblookup "$LOOKUP_SERVER" 2>/dev/null | awk '/^[0-9]+\./ { print $1; exit }') close_netbios_lookup [ "$RESOLVED_SERVER" != "" ] && echo "$RESOLVED_SERVER" && return 0 return 1 } resolve_named_server() { resolve_dns_server "$1" && return 0 resolve_netbios_server "$1" } cleanup_on_exit() { close_netbios_lookup end_root_edit } trap cleanup_on_exit EXIT trap 'cleanup_on_exit; exit 1' HUP TERM trap 'cleanup_on_exit; exit 130' INT record_mount_failure() { MOUNT_FAILURES=$((MOUNT_FAILURES + 1)) } get_mount_info() { local PATH_TO_CHECK="$1" local LINE local SOURCE local REST local TARGET local TYPE_REST MOUNT_SOURCE_FOR_TARGET="" MOUNT_TYPE_FOR_TARGET="" while IFS= read -r LINE do SOURCE=${LINE%% on *} REST=${LINE#* on } [ "$REST" != "$LINE" ] || continue TARGET=${REST%% type *} [ "$TARGET" == "$PATH_TO_CHECK" ] || continue TYPE_REST=${REST#* type } [ "$TYPE_REST" != "$REST" ] || return 1 MOUNT_SOURCE_FOR_TARGET="$SOURCE" MOUNT_TYPE_FOR_TARGET=${TYPE_REST%% *} return 0 done < /dev/null 2>&1 if target_is_mounted "$TARGET" then echo "$LABEL already mounted" return 0 fi if mount -t cifs "$SOURCE" "$TARGET" -o "$MOUNT_OPTIONS" then echo "$LABEL mounted" return 0 fi echo "$LABEL not mounted" record_mount_failure return 1 } mount_bind_target() { local SOURCE="$1" local TARGET="$2" local LABEL="$3" mkdir -p "$TARGET" > /dev/null 2>&1 if target_is_mounted "$TARGET" then echo "$LABEL already mounted" return 0 fi if mount --bind "$SOURCE" "$TARGET" then echo "$LABEL mounted" return 0 fi echo "$LABEL not mounted" record_mount_failure return 1 } unmount_temp_bind_mounts() { local TEMP_MOUNT="$1" local LINE local SOURCE local REST local TARGET while IFS= read -r LINE do SOURCE=${LINE%% on *} case "$SOURCE" in "$TEMP_MOUNT"/*) ;; *) continue ;; esac REST=${LINE#* on } [ "$REST" != "$LINE" ] || continue TARGET=${REST%% type *} echo "Recovering stale ${TARGET##*/} bind mount" umount "$TARGET" >/dev/null 2>&1 || true done < /dev/null 2>&1 if target_is_mounted "$TEMP_MOUNT" then if [ "$MOUNT_TYPE_FOR_TARGET" == "cifs" ] && [ "$MOUNT_SOURCE_FOR_TARGET" == "$MOUNT_SOURCE" ] then echo "$MOUNT_SOURCE already mounted" return 0 fi echo "Recovering stale ${TEMP_MOUNT} mount" unmount_temp_bind_mounts "$TEMP_MOUNT" if ! umount "$TEMP_MOUNT" then echo "$MOUNT_SOURCE not mounted" record_mount_failure return 1 fi fi mount_cifs_target "$MOUNT_SOURCE" "$TEMP_MOUNT" "$MOUNT_SOURCE" } remove_legacy_network_hooks() { local HOOK_PATHS local HOOK_PATH local TOUCHED="false" HOOK_PATHS="/etc/network/if-up.d/mount_cifs|/etc/network/if-down.d/mount_cifs|/etc/network/if-up.d/cifs_mount|/etc/network/if-down.d/cifs_mount|/etc/network/if-up.d/${SCRIPT_NAME}|/etc/network/if-down.d/${SCRIPT_NAME}" local OLD_IFS="$IFS" IFS="|" for HOOK_PATH in $HOOK_PATHS do [ -e "$HOOK_PATH" ] || continue if [ "$TOUCHED" == "false" ] then begin_root_edit || return 1 TOUCHED="true" fi rm "$HOOK_PATH" >/dev/null 2>&1 || true done IFS="$OLD_IFS" [ "$TOUCHED" == "true" ] && end_root_edit } ensure_user_startup() { [ -e /etc/init.d/S99user ] || return 1 if [ ! -e "$USER_STARTUP" ] then if [ -e "$USER_STARTUP_TEMPLATE" ] then cp "$USER_STARTUP_TEMPLATE" "$USER_STARTUP" else printf '#!/bin/sh\n\n' > "$USER_STARTUP" fi fi chmod +x "$USER_STARTUP" >/dev/null 2>&1 || true return 0 } remove_user_startup_entry() { local TMP_STARTUP [ -e "$USER_STARTUP" ] || return 0 TMP_STARTUP="/tmp/${SCRIPT_NAME}_startup.$$" awk -v begin_marker="$STARTUP_BEGIN_MARKER" -v end_marker="$STARTUP_END_MARKER" -v legacy_marker="$STARTUP_LEGACY_MARKER" -v startup_match="$STARTUP_MATCH" ' $0 == begin_marker { skip = 1; next } $0 == end_marker { skip = 0; next } skip { next } index($0, legacy_marker) { next } index($0, startup_match) { next } { print } ' "$USER_STARTUP" > "$TMP_STARTUP" || { rm -f "$TMP_STARTUP"; return 1; } if cmp -s "$TMP_STARTUP" "$USER_STARTUP" then rm -f "$TMP_STARTUP" return 0 fi cat "$TMP_STARTUP" > "$USER_STARTUP" rm -f "$TMP_STARTUP" BOOT_CONFIG_CHANGED="true" chmod +x "$USER_STARTUP" >/dev/null 2>&1 || true return 0 } install_user_startup_entry() { local TMP_STARTUP ensure_user_startup || return 1 TMP_STARTUP="/tmp/${SCRIPT_NAME}_startup.$$" awk -v begin_marker="$STARTUP_BEGIN_MARKER" -v end_marker="$STARTUP_END_MARKER" -v legacy_marker="$STARTUP_LEGACY_MARKER" -v startup_match="$STARTUP_MATCH" ' $0 == begin_marker { skip = 1; next } $0 == end_marker { skip = 0; next } skip { next } index($0, legacy_marker) { next } index($0, startup_match) { next } { print } ' "$USER_STARTUP" > "$TMP_STARTUP" || { rm -f "$TMP_STARTUP"; return 1; } printf '\n%s\n%s\n%s\n' "$STARTUP_BEGIN_MARKER" "$STARTUP_COMMAND" "$STARTUP_END_MARKER" >> "$TMP_STARTUP" if cmp -s "$TMP_STARTUP" "$USER_STARTUP" then rm -f "$TMP_STARTUP" return 0 fi cat "$TMP_STARTUP" > "$USER_STARTUP" || { rm -f "$TMP_STARTUP"; return 1; } rm -f "$TMP_STARTUP" BOOT_CONFIG_CHANGED="true" chmod +x "$USER_STARTUP" >/dev/null 2>&1 || true return 0 } remove_init_service() { if [ -e "$INIT_SERVICE_PATH" ] then begin_root_edit || return 1 rm "$INIT_SERVICE_PATH" >/dev/null 2>&1 || true BOOT_CONFIG_CHANGED="true" end_root_edit fi } install_init_service() { local TMP_SERVICE TMP_SERVICE="/tmp/${SCRIPT_NAME}_init.$$" cat > "$TMP_SERVICE" < "$INIT_SERVICE_PATH" || { rm -f "$TMP_SERVICE"; end_root_edit; return 1; } rm -f "$TMP_SERVICE" chmod +x "$INIT_SERVICE_PATH" BOOT_CONFIG_CHANGED="true" end_root_edit } configure_boot_mount() { local BOOT_TARGET BOOT_CONFIG_CHANGED="false" if [ "$MOUNT_AT_BOOT" == "true" ] then WAIT_FOR_SERVER="true" if install_user_startup_entry then BOOT_TARGET="$USER_STARTUP" remove_init_service else install_init_service || return 1 BOOT_TARGET="$INIT_SERVICE_PATH" fi [ "$BOOT_CONFIG_CHANGED" == "true" ] && echo "Boot automount enabled via ${BOOT_TARGET}." else remove_user_startup_entry || true remove_init_service [ "$BOOT_CONFIG_CHANGED" == "true" ] && echo "Boot automount disabled." fi } wait_for_network_ready() { local TIMEOUT local WAITED if [ "${BOOT_START_DELAY_SECONDS:-0}" -gt 0 ] 2>/dev/null then sleep "$BOOT_START_DELAY_SECONDS" fi if ! command -v ip >/dev/null 2>&1 then return 0 fi TIMEOUT="${NETWORK_READY_TIMEOUT_SECONDS:-45}" case "$TIMEOUT" in ''|*[!0-9]*) TIMEOUT="45" ;; esac WAITED=0 echo "Waiting for network" until ip -o -4 addr show up scope global 2>/dev/null | grep -q . do if [ "$TIMEOUT" -gt 0 ] && [ "$WAITED" -ge "$TIMEOUT" ] then echo "Network not ready after ${TIMEOUT} seconds." return 1 fi sleep 1 WAITED=$((WAITED + 1)) done } default_route_exists() { if command -v ip >/dev/null 2>&1 then ip route show default 2>/dev/null | grep -q . && return 0 fi if command -v route >/dev/null 2>&1 then route -n 2>/dev/null | grep -q '^0\.0\.0\.0' && return 0 fi return 1 } global_ipv4_interface_count() { local COUNT if ! command -v ip >/dev/null 2>&1 then echo "0" return 0 fi COUNT=$(ip -o -4 addr show up scope global 2>/dev/null | cut -d' ' -f2 | sort -u | wc -l | tr -d ' ') case "$COUNT" in ''|*[!0-9]*) COUNT="0" ;; esac echo "$COUNT" } wait_for_default_route() { local TIMEOUT local WAITED local INTERFACE_COUNT local SETTLE_SECONDS if ! command -v ip >/dev/null 2>&1 && ! command -v route >/dev/null 2>&1 then return 0 fi TIMEOUT="${DEFAULT_ROUTE_READY_TIMEOUT_SECONDS:-30}" case "$TIMEOUT" in ''|*[!0-9]*) TIMEOUT="30" ;; esac WAITED=0 echo "Waiting for default route" until default_route_exists do if [ "$TIMEOUT" -gt 0 ] && [ "$WAITED" -ge "$TIMEOUT" ] then echo "Default route not ready after ${TIMEOUT} seconds." return 1 fi sleep 1 WAITED=$((WAITED + 1)) done INTERFACE_COUNT=$(global_ipv4_interface_count) if [ "$INTERFACE_COUNT" -gt 1 ] 2>/dev/null then MULTI_INTERFACE_BOOT="true" SETTLE_SECONDS="${DUAL_INTERFACE_SETTLE_SECONDS:-5}" case "$SETTLE_SECONDS" in ''|*[!0-9]*) SETTLE_SECONDS="5" ;; esac if [ "$SETTLE_SECONDS" -gt 0 ] then echo "Settling dual-interface routing for ${SETTLE_SECONDS} seconds" sleep "$SETTLE_SECONDS" fi fi } restart_ntp_after_boot_mount() { [ "$BOOT_START" == "true" ] || return 0 case "$RESTART_NTP_AFTER_BOOT_MOUNT" in true) ;; auto) [ "$MULTI_INTERFACE_BOOT" == "true" ] || return 0 ;; *) return 0 ;; esac [ -x "$NTP_INIT_SCRIPT" ] || return 0 echo "Restarting NTP" if ! "$NTP_INIT_SCRIPT" restart >/dev/null 2>&1 then echo "NTP restart failed" fi } remove_legacy_network_hooks || true if [ "$BOOT_START" == "true" ] && [ "$MOUNT_AT_BOOT" != "true" ] then exit 0 fi if [ "$BOOT_START" != "true" ] && [ "$MOUNT_AT_BOOT" != "true" ] then configure_boot_mount || true fi if [ "$SERVER" == "" ] then echo "Please configure" echo "this script" echo "either editing" echo "${ORIGINAL_SCRIPT_PATH##*/}" echo "or making a new" echo "${INI_PATH##*/}" exit 1 fi if [ "$BOOT_START" != "true" ] && [ "$MOUNT_AT_BOOT" == "true" ] then configure_boot_mount || exit 1 elif [ "$BOOT_START" == "true" ] then WAIT_FOR_SERVER="true" wait_for_network_ready || exit 1 wait_for_default_route || exit 1 fi for KERNEL_MODULE in $KERNEL_MODULES; do if ! cat /lib/modules/$(uname -r)/modules.builtin | grep -q "$(echo "$KERNEL_MODULE" | sed 's/\./\\\./g')" then if ! lsmod | grep -q "${KERNEL_MODULE%.*}" then echo "The current Kernel doesn't" echo "support CIFS (SAMBA)." echo "Please update your" echo "MiSTer Linux system." exit 1 # if ! insmod "/media/fat/linux/$KERNEL_MODULE" > /dev/null 2>&1 # then # echo "Downloading $KERNEL_MODULE" # curl -L "$MISTER_CIFS_URL/blob/master/$KERNEL_MODULE?raw=true" -o "/media/fat/linux/$KERNEL_MODULE" # case $? in # 0) # ;; # 60) # if ! curl -kL "$MISTER_CIFS_URL/blob/master/$KERNEL_MODULE?raw=true" -o "/media/fat/linux/$KERNEL_MODULE" # then # echo "No Internet connection" # exit 2 # fi # ;; # *) # echo "No Internet connection" # exit 2 # ;; # esac # if ! insmod "/media/fat/linux/$KERNEL_MODULE" > /dev/null 2>&1 # then # echo "Unable to load $KERNEL_MODULE" # exit 1 # fi # fi fi fi done if [ "$USERNAME" == "" ] then MOUNT_OPTIONS="sec=none" else MOUNT_OPTIONS="username=$USERNAME,password=$PASSWORD" if [ "$DOMAIN" != "" ] then MOUNT_OPTIONS="$MOUNT_OPTIONS,domain=$DOMAIN" fi fi if [ "$ADDITIONAL_MOUNT_OPTIONS" != "" ] then MOUNT_OPTIONS="$MOUNT_OPTIONS,$ADDITIONAL_MOUNT_OPTIONS" fi if ! is_ipv4_literal "$SERVER" then SERVER_WAIT_TIMEOUT="${SERVER_WAIT_TIMEOUT_SECONDS:-60}" case "$SERVER_WAIT_TIMEOUT" in ''|*[!0-9]*) SERVER_WAIT_TIMEOUT="60" ;; esac if [ "$WAIT_FOR_SERVER" == "true" ] then SERVER_WAITED=0 echo "Waiting for $SERVER" until RESOLVED_SERVER=$(resolve_named_server "$SERVER") do if [ "$SERVER_WAIT_TIMEOUT" -gt 0 ] && [ "$SERVER_WAITED" -ge "$SERVER_WAIT_TIMEOUT" ] then echo "$SERVER not found after ${SERVER_WAIT_TIMEOUT} seconds." exit 1 fi sleep 1 SERVER_WAITED=$((SERVER_WAITED + 1)) done else RESOLVED_SERVER=$(resolve_named_server "$SERVER") fi if [ "$RESOLVED_SERVER" == "" ] then echo "$SERVER not found." exit 1 fi SERVER="$RESOLVED_SERVER" else if [ "$WAIT_FOR_SERVER" == "true" ] then SERVER_WAIT_TIMEOUT="${SERVER_WAIT_TIMEOUT_SECONDS:-60}" case "$SERVER_WAIT_TIMEOUT" in ''|*[!0-9]*) SERVER_WAIT_TIMEOUT="60" ;; esac SERVER_WAITED=0 echo "Waiting for $SERVER" until ping -q -w1 -c1 "$SERVER" &>/dev/null do if [ "$SERVER_WAIT_TIMEOUT" -gt 0 ] && [ "$SERVER_WAITED" -ge "$SERVER_WAIT_TIMEOUT" ] then echo "$SERVER not reachable after ${SERVER_WAIT_TIMEOUT} seconds." exit 1 fi sleep 1 SERVER_WAITED=$((SERVER_WAITED + 1)) done fi fi MOUNT_SOURCE="//$SERVER/$SHARE" if [ -n "$SHARE_DIRECTORY" ] && [ -n "$MOUNT_SOURCE" ] then MOUNT_SOURCE="$MOUNT_SOURCE/$SHARE_DIRECTORY" fi if [ "$LOCAL_DIR" == "*" ] || { echo "$LOCAL_DIR" | grep -q "|"; } then if [ "$SINGLE_CIFS_CONNECTION" == "true" ] then if prepare_temp_mount then if [ "$LOCAL_DIR" == "*" ] then LOCAL_DIR="" for DIRECTORY in "/tmp/$SCRIPT_NAME"/* do if [ -d "$DIRECTORY" ] then DIRECTORY=$(basename "$DIRECTORY") for SPECIAL_DIRECTORY in $SPECIAL_DIRECTORIES do if [ "$DIRECTORY" == "$SPECIAL_DIRECTORY" ] then DIRECTORY="" break fi done if [ "$DIRECTORY" != "" ] then if [ "$LOCAL_DIR" != "" ] then LOCAL_DIR="$LOCAL_DIR|" fi LOCAL_DIR="$LOCAL_DIR$DIRECTORY" fi fi done fi for DIRECTORY in $LOCAL_DIR do mount_bind_target "/tmp/$SCRIPT_NAME/$DIRECTORY" "$BASE_PATH/$DIRECTORY" "$DIRECTORY" done fi else if [ "$LOCAL_DIR" == "*" ] then LOCAL_DIR="" for DIRECTORY in "$BASE_PATH"/* do if [ -d "$DIRECTORY" ] then DIRECTORY=$(basename "$DIRECTORY") for SPECIAL_DIRECTORY in $SPECIAL_DIRECTORIES do if [ "$DIRECTORY" == "$SPECIAL_DIRECTORY" ] then DIRECTORY="" break fi done if [ "$DIRECTORY" != "" ] then if [ "$LOCAL_DIR" != "" ] then LOCAL_DIR="$LOCAL_DIR|" fi LOCAL_DIR="$LOCAL_DIR$DIRECTORY" fi fi done fi for DIRECTORY in $LOCAL_DIR do mount_cifs_target "$MOUNT_SOURCE/$DIRECTORY" "$BASE_PATH/$DIRECTORY" "$DIRECTORY" done fi else mount_cifs_target "$MOUNT_SOURCE" "$BASE_PATH/$LOCAL_DIR" "$LOCAL_DIR" fi if [ "$MOUNT_FAILURES" -gt 0 ] then echo "Done with ${MOUNT_FAILURES} failure(s)." exit 1 fi restart_ntp_after_boot_mount echo "Done!" exit 0