fallback to file editing in case file is locked

This commit is contained in:
Nikos Atlas 2022-05-19 16:41:27 +03:00 committed by Brian May
parent 553bc2b70c
commit 1def53e085
2 changed files with 30 additions and 4 deletions

View File

@ -1,4 +1,5 @@
import errno
import shutil
import socket
import signal
import sys
@ -30,7 +31,10 @@ def rewrite_etc_hosts(hostmap, port):
else:
raise
if old_content.strip() and not os.path.exists(BAKFILE):
os.link(HOSTSFILE, BAKFILE)
try:
os.link(HOSTSFILE, BAKFILE)
except OSError:
shutil.copyfile(HOSTSFILE, BAKFILE)
tmpname = "%s.%d.tmp" % (HOSTSFILE, port)
f = open(tmpname, 'w')
for line in old_content.rstrip().split('\n'):
@ -47,7 +51,10 @@ def rewrite_etc_hosts(hostmap, port):
else:
os.chown(tmpname, 0, 0)
os.chmod(tmpname, 0o600)
os.rename(tmpname, HOSTSFILE)
try:
os.rename(tmpname, HOSTSFILE)
except OSError:
shutil.move(tmpname, HOSTSFILE)
def restore_etc_hosts(hostmap, port):

View File

@ -1,7 +1,11 @@
import io
import os
from socket import AF_INET, AF_INET6
from unittest.mock import Mock, patch, call
import pytest
import sshuttle.firewall
@ -59,6 +63,21 @@ def test_rewrite_etc_hosts(tmpdir):
assert orig_hosts.computehash() == new_hosts.computehash()
@patch('os.link')
@patch('os.rename')
def test_rewrite_etc_hosts_no_overwrite(mock_link, mock_rename, tmpdir):
mock_link.side_effect = OSError
mock_rename.side_effect = OSError
with pytest.raises(OSError):
os.link('/test_from', '/test_to')
with pytest.raises(OSError):
os.rename('/test_from', '/test_to')
test_rewrite_etc_hosts(tmpdir)
def test_subnet_weight():
subnets = [
(AF_INET, 16, 0, '192.168.0.0', 0, 0),
@ -123,7 +142,7 @@ def test_main(mock_get_method, mock_setup_daemon, mock_rewrite_etc_hosts):
[(AF_INET6, u'2404:6800:4004:80c::33')],
AF_INET6,
[(AF_INET6, 64, False, u'2404:6800:4004:80c::', 0, 0),
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 80, 80)],
(AF_INET6, 128, True, u'2404:6800:4004:80c::101f', 80, 80)],
True,
None,
'0x01'),
@ -132,7 +151,7 @@ def test_main(mock_get_method, mock_setup_daemon, mock_rewrite_etc_hosts):
[(AF_INET, u'1.2.3.33')],
AF_INET,
[(AF_INET, 24, False, u'1.2.3.0', 8000, 9000),
(AF_INET, 32, True, u'1.2.3.66', 8080, 8080)],
(AF_INET, 32, True, u'1.2.3.66', 8080, 8080)],
True,
None,
'0x01'),