libnetwork/etchosts: keep file open when updating hosts

Open the hosts file once for both reading and writing, instead of reading
and writing it through separate file operations.

This keeps the update on the same file handle, avoids reopening the path
between the read and write, and preserves the existing file metadata.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn committed 2026-10-01 14:11:29 +02:00
1 parent 012b2efc0e
commit 357096e924
1 file changed
+20 -4
+20 -4
View File
@@ -169,16 +169,32 @@ loop:
// path is path to host file
// IP is new IP address
// hostname is hostname to search for to replace IP
func Update(path, IP, hostname string) error {
func Update(path, IP, hostname string) (retErr error) {
re, err := regexp.Compile(fmt.Sprintf(`(\S*)(\t%s)(\s|\.)`, regexp.QuoteMeta(hostname)))
if err != nil {
return err
}
defer pathLock(path)()
old, err := os.ReadFile(path)
defer pathLock(path)()
f, err := os.OpenFile(path, os.O_RDWR, 0)
if err != nil {
return err
}
return os.WriteFile(path, re.ReplaceAll(old, []byte(IP+"$2"+"$3")), 0o644) // #nosec G703 -- path argument is from trusted source.
defer func() {
if err := f.Close(); retErr == nil {
retErr = err
}
}()
old, err := io.ReadAll(f)
if err != nil {
return err
}
updated := re.ReplaceAll(old, []byte(IP+"$2"+"$3"))
if err := f.Truncate(0); err != nil {
return err
}
_, err = f.WriteAt(updated, 0)
return err
}