diff options
author | Andrej Shadura <andrew.shadura@collabora.co.uk> | 2020-01-16 15:25:17 +0100 |
---|---|---|
committer | Andrej Shadura <andrew.shadura@collabora.co.uk> | 2020-01-16 15:25:17 +0100 |
commit | fef5746ee329eb560d740132895ed29a44e44d10 (patch) | |
tree | acbe7190a025de95c107fce342e2d2175aa88e2f /commands.go | |
parent | afdeba754f8766de3b12211953eced5304991cde (diff) |
New upstream version 1.0.0+git20191223.292995b
Diffstat (limited to 'commands.go')
-rw-r--r-- | commands.go | 118 |
1 files changed, 113 insertions, 5 deletions
diff --git a/commands.go b/commands.go index 0ea2b9a..52704c5 100644 --- a/commands.go +++ b/commands.go @@ -2,8 +2,10 @@ package debos import ( "bytes" + "crypto/sha256" "fmt" "io" + "io/ioutil" "log" "os" "os/exec" @@ -115,9 +117,101 @@ func (cmd *Command) AddBindMount(source, target string) { cmd.bindMounts = append(cmd.bindMounts, mount) } +func (cmd *Command) saveResolvConf() (*[sha256.Size]byte, error) { + hostconf := "/etc/resolv.conf" + chrootedconf := path.Join(cmd.Chroot, hostconf) + savedconf := chrootedconf + ".debos" + var sum [sha256.Size]byte + + if cmd.ChrootMethod == CHROOT_METHOD_NONE { + return nil, nil + } + + // There may not be an existing resolv.conf + if _, err := os.Lstat(chrootedconf); !os.IsNotExist(err) { + if err = os.Rename(chrootedconf, savedconf); err != nil { + return nil, err + } + } + + /* Expect a relatively small file here */ + data, err := ioutil.ReadFile(hostconf) + if err != nil { + return nil, err + } + out := []byte("# Automatically generated by Debos\n") + out = append(out, data...) + + sum = sha256.Sum256(out) + + err = ioutil.WriteFile(chrootedconf, out, 0644) + if err != nil { + return nil, err + } + + return &sum, nil +} + +func (cmd *Command) restoreResolvConf(sum *[sha256.Size]byte) error { + hostconf := "/etc/resolv.conf" + chrootedconf := path.Join(cmd.Chroot, hostconf) + savedconf := chrootedconf + ".debos" + + if cmd.ChrootMethod == CHROOT_METHOD_NONE || sum == nil { + return nil + } + + // Remove the original copy anyway + defer os.Remove(savedconf) + + fi, err := os.Lstat(chrootedconf) + + // resolv.conf was removed during the command call + // Nothing to do with it -- file has been changed anyway + if os.IsNotExist(err) { + return nil + } + + mode := fi.Mode() + switch { + case mode.IsRegular(): + // Try to calculate checksum + data, err := ioutil.ReadFile(chrootedconf) + if err != nil { + return err + } + currentsum := sha256.Sum256(data) + + // Leave the changed resolv.conf untouched + if bytes.Compare(currentsum[:], (*sum)[:]) == 0 { + // Remove the generated version + if err := os.Remove(chrootedconf); err != nil { + return err + } + + if _, err := os.Lstat(savedconf); !os.IsNotExist(err) { + // Restore the original version + if err = os.Rename(savedconf, chrootedconf); err != nil { + return err + } + } + } + case mode&os.ModeSymlink != 0: + // If the 'resolv.conf' is a symlink + // Nothing to do with it -- file has been changed anyway + default: + // File is not regular or symlink + // Let's get out here with verbose message + log.Printf("Warning: /etc/resolv.conf inside the chroot is not a regular file") + } + + return nil +} + func (cmd Command) Run(label string, cmdline ...string) error { q := newQemuHelper(cmd) q.Setup() + defer q.Cleanup() var options []string switch cmd.ChrootMethod { @@ -128,7 +222,8 @@ func (cmd Command) Run(label string, cmdline ...string) error { options = append(options, cmd.Chroot) options = append(options, cmdline...) case CHROOT_METHOD_NSPAWN: - options = append(options, "systemd-nspawn", "-q", "-D", cmd.Chroot) + // We use own resolv.conf handling + options = append(options, "systemd-nspawn", "-q", "--resolv-conf=off", "-D", cmd.Chroot) for _, e := range cmd.extraEnv { options = append(options, "--setenv", e) @@ -147,6 +242,8 @@ func (cmd Command) Run(label string, cmdline ...string) error { exe.Stdout = w exe.Stderr = w + defer w.flush() + if len(cmd.extraEnv) > 0 && cmd.ChrootMethod != CHROOT_METHOD_NSPAWN { exe.Env = append(os.Environ(), cmd.extraEnv...) } @@ -158,11 +255,22 @@ func (cmd Command) Run(label string, cmdline ...string) error { defer services.Allow() } - err := exe.Run() - w.flush() - q.Cleanup() + // Save the original resolv.conf and copy version from host + resolvsum, err := cmd.saveResolvConf() + if err != nil { + return err + } + + if err = exe.Run(); err != nil { + return err + } + + // Restore the original resolv.conf if not changed + if err = cmd.restoreResolvConf(resolvsum); err != nil { + return err + } - return err + return nil } type qemuHelper struct { |