Fix smb.conf section removal deleting everything after the target share

Reported live: Samba broke on the home box after this ran. Root cause
confirmed by reproducing it directly: the old removal step used
`sed -i "/^\[share\]$/,/^$/d"` — a range delete from the share's header
through the next BLANK line. A home box whose smb.conf has no blank line
separating sections (common — nothing requires one) means that range
never finds a terminator and sed deletes straight through to end of file,
taking every share defined after the target one down with it. Reproduced
against a 4-section smb.conf with no blank lines: the old approach left
only [global] standing, silently destroying two unrelated, pre-existing
shares that had nothing to do with this tool.

Replaced with an awk pass that removes lines from the target share's own
[header] up to the next `[section]` header or EOF — the actual boundary
of an INI-style section, independent of blank-line formatting. Also now
builds the new config in a scratch file and validates it with `testparm`
before it's ever copied over the live smb.conf; on validation failure it
leaves the existing file untouched and exits instead of restarting smbd
against a config that might not even parse. The existing
smb.conf.backup.<timestamp> step (already present before this fix) is
what the user is recovering the home box with in the meantime.

Verified the fix against the exact reproduction: the same 4-section,
no-blank-line smb.conf now retains all three untouched sections after
removing only the target one.
This commit is contained in:
Claude
2026-08-10 19:18:55 +00:00
parent 82fad864ac
commit a2d3b0a651
+23 -3
View File
@@ -364,12 +364,25 @@ _vdm_setup_remote_samba() {
sudo smbpasswd -e '${user}'"
fi
# Builds the new config in a scratch file and validates it with
# testparm BEFORE it ever touches the live smb.conf — confirmed live:
# the previous approach here (sed range-deleting from the [share_name]
# header through the next BLANK line) silently deleted straight through
# to end of file on a home box whose smb.conf had no blank line
# separating sections, taking unrelated shares down with it. Section
# removal now stops at the next `[section]` header (or EOF) instead of
# a blank line, which is the actual boundary of an INI-style section
# regardless of how the file happens to be formatted.
local remote_cmd
remote_cmd=$(cat << REMOTECMD
set -e
sudo mkdir -p '${remote_path}'
sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.backup.\$(date +%Y%m%d-%H%M%S) 2>/dev/null || true
sudo sed -i "/^\\[${share_name}\\]\$/,/^\$/d" /etc/samba/smb.conf
BACKUP="/etc/samba/smb.conf.backup.\$(date +%Y%m%d-%H%M%S)"
sudo cp /etc/samba/smb.conf "\$BACKUP"
sudo awk -v target='[${share_name}]' '
/^\\[/ { skip = (\$0 == target) }
!skip { print }
' /etc/samba/smb.conf > /tmp/smb.conf.vdm.new
{
echo ""
echo "[${share_name}]"
@@ -379,7 +392,14 @@ sudo sed -i "/^\\[${share_name}\\]\$/,/^\$/d" /etc/samba/smb.conf
echo " guest ok = no"
echo " valid users = ${user}"
echo " force user = ${user}"
} | sudo tee -a /etc/samba/smb.conf >/dev/null
} >> /tmp/smb.conf.vdm.new
if sudo testparm -s /tmp/smb.conf.vdm.new >/dev/null 2>&1; then
sudo cp /tmp/smb.conf.vdm.new /etc/samba/smb.conf
rm -f /tmp/smb.conf.vdm.new
else
echo "New smb.conf failed testparm validation — leaving the existing config untouched. Backup at \$BACKUP, rejected draft at /tmp/smb.conf.vdm.new for inspection." >&2
exit 1
fi
${pw_cmd}
sudo systemctl restart smbd
command -v ufw >/dev/null 2>&1 && sudo ufw allow samba >/dev/null 2>&1 || true