|
|
|
|
@ -7,11 +7,14 @@ |
|
|
|
|
package hostinfo |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"bufio" |
|
|
|
|
"io" |
|
|
|
|
"os" |
|
|
|
|
"path/filepath" |
|
|
|
|
"runtime" |
|
|
|
|
"strings" |
|
|
|
|
"sync/atomic" |
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"go4.org/mem" |
|
|
|
|
"tailscale.com/tailcfg" |
|
|
|
|
@ -224,3 +227,55 @@ func inKubernetes() bool { |
|
|
|
|
} |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type etcAptSrcResult struct { |
|
|
|
|
mod time.Time |
|
|
|
|
disabled bool |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var etcAptSrcCache atomic.Value // of etcAptSrcResult
|
|
|
|
|
|
|
|
|
|
// DisabledEtcAptSource reports whether Ubuntu (or similar) has disabled
|
|
|
|
|
// the /etc/apt/sources.list.d/tailscale.list file contents upon upgrade
|
|
|
|
|
// to a new release of the distro.
|
|
|
|
|
//
|
|
|
|
|
// See https://github.com/tailscale/tailscale/issues/3177
|
|
|
|
|
func DisabledEtcAptSource() bool { |
|
|
|
|
if runtime.GOOS != "linux" { |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
const path = "/etc/apt/sources.list.d/tailscale.list" |
|
|
|
|
fi, err := os.Stat(path) |
|
|
|
|
if err != nil || !fi.Mode().IsRegular() { |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
mod := fi.ModTime() |
|
|
|
|
if c, ok := etcAptSrcCache.Load().(etcAptSrcResult); ok && c.mod == mod { |
|
|
|
|
return c.disabled |
|
|
|
|
} |
|
|
|
|
f, err := os.Open(path) |
|
|
|
|
if err != nil { |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
defer f.Close() |
|
|
|
|
v := etcAptSourceFileIsDisabled(f) |
|
|
|
|
etcAptSrcCache.Store(etcAptSrcResult{mod: mod, disabled: v}) |
|
|
|
|
return v |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func etcAptSourceFileIsDisabled(r io.Reader) bool { |
|
|
|
|
bs := bufio.NewScanner(r) |
|
|
|
|
disabled := false // did we find the "disabled on upgrade" comment?
|
|
|
|
|
for bs.Scan() { |
|
|
|
|
line := strings.TrimSpace(bs.Text()) |
|
|
|
|
if strings.Contains(line, "# disabled on upgrade") { |
|
|
|
|
disabled = true |
|
|
|
|
} |
|
|
|
|
if line == "" || line[0] == '#' { |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
// Well, it has some contents in it at least.
|
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
return disabled |
|
|
|
|
} |
|
|
|
|
|