[1/3] unbound-dhcp-leases-bridge: Implement atomic file replacement

Message ID 20240426150919.3766772-1-michael.tremer@ipfire.org
State Staged
Commit c3cabfa09cac245f0a950d31d0f4283741017bd5
Headers
Series [1/3] unbound-dhcp-leases-bridge: Implement atomic file replacement |

Commit Message

Michael Tremer April 26, 2024, 3:09 p.m. UTC
  This change no longer renames the file, but removes the old link and
creates a new link for the temporary file. That helps us to jump out of
the code at any point without worrying about cleaning up the temporary
file.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
---
 config/unbound/unbound-dhcp-leases-bridge | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
  

Comments

Nick Howitt April 30, 2024, 10:41 a.m. UTC | #1
On 26/04/2024 16:09, Michael Tremer wrote:
> This change no longer renames the file, but removes the old link and
> creates a new link for the temporary file. That helps us to jump out of
> the code at any point without worrying about cleaning up the temporary
> file.
>
> Signed-off-by: Michael Tremer<michael.tremer@ipfire.org>
> ---
>   config/unbound/unbound-dhcp-leases-bridge | 10 ++++++++--
>   1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/config/unbound/unbound-dhcp-leases-bridge b/config/unbound/unbound-dhcp-leases-bridge
> index e9f022aff..5d5696af0 100644
> --- a/config/unbound/unbound-dhcp-leases-bridge
> +++ b/config/unbound/unbound-dhcp-leases-bridge
> @@ -526,16 +526,22 @@ class UnboundConfigWriter(object):
>   	def write_dhcp_leases(self, leases):
>   		log.debug("Writing DHCP leases...")
>   
> -		with tempfile.NamedTemporaryFile(mode="w", delete=False) as f:
> +		with tempfile.NamedTemporaryFile(mode="w") as f:
>   			for l in leases:
>   				for rr in l.rrset:
>   					f.write("local-data: \"%s\"\n" % " ".join(rr))
>   
> +			# Flush the file
> +			f.flush()
> +
>   			# Make file readable for everyone
>   			os.fchmod(f.fileno(), stat.S_IRUSR|stat.S_IWUSR|stat.S_IRGRP|stat.S_IROTH)
>   
> +			# Remove the old file
> +			os.unlink(self.path)
> +
>   			# Move the file to its destination
> -			os.rename(f.name, self.path)
> +			os.link(f.name, self.path)
>   
>   	def _control(self, *args):
>   		command = ["unbound-control"]
|Signed-off-by: Nick Howitt <nick@howitts.co.uk>|
  

Patch

diff --git a/config/unbound/unbound-dhcp-leases-bridge b/config/unbound/unbound-dhcp-leases-bridge
index e9f022aff..5d5696af0 100644
--- a/config/unbound/unbound-dhcp-leases-bridge
+++ b/config/unbound/unbound-dhcp-leases-bridge
@@ -526,16 +526,22 @@  class UnboundConfigWriter(object):
 	def write_dhcp_leases(self, leases):
 		log.debug("Writing DHCP leases...")
 
-		with tempfile.NamedTemporaryFile(mode="w", delete=False) as f:
+		with tempfile.NamedTemporaryFile(mode="w") as f:
 			for l in leases:
 				for rr in l.rrset:
 					f.write("local-data: \"%s\"\n" % " ".join(rr))
 
+			# Flush the file
+			f.flush()
+
 			# Make file readable for everyone
 			os.fchmod(f.fileno(), stat.S_IRUSR|stat.S_IWUSR|stat.S_IRGRP|stat.S_IROTH)
 
+			# Remove the old file
+			os.unlink(self.path)
+
 			# Move the file to its destination
-			os.rename(f.name, self.path)
+			os.link(f.name, self.path)
 
 	def _control(self, *args):
 		command = ["unbound-control"]