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:
1 file changed
+20
-4
@@ -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
|
||||
}
|
||||
Reference in new issue
Block a user