Fix panic in parsing /etc/os-release
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
parent
55c8a5b21b
commit
bffb7509bb
2 changed files with 131 additions and 36 deletions
|
@ -3,9 +3,14 @@
|
|||
package operatingsystem
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/mattn/go-shellwords"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -18,15 +23,34 @@ var (
|
|||
|
||||
// GetOperatingSystem gets the name of the current operating system.
|
||||
func GetOperatingSystem() (string, error) {
|
||||
b, err := ioutil.ReadFile(etcOsRelease)
|
||||
osReleaseFile, err := os.Open(etcOsRelease)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if i := bytes.Index(b, []byte("PRETTY_NAME")); i >= 0 {
|
||||
b = b[i+13:]
|
||||
return string(b[:bytes.IndexByte(b, '"')]), nil
|
||||
defer osReleaseFile.Close()
|
||||
|
||||
var prettyName string
|
||||
scanner := bufio.NewScanner(osReleaseFile)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.HasPrefix(line, "PRETTY_NAME=") {
|
||||
data := strings.SplitN(line, "=", 2)
|
||||
prettyNames, err := shellwords.Parse(data[1])
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("PRETTY_NAME is invalid: %s", err.Error())
|
||||
}
|
||||
return "", errors.New("PRETTY_NAME not found")
|
||||
if len(prettyNames) != 1 {
|
||||
return "", fmt.Errorf("PRETTY_NAME needs to be enclosed by quotes if they have spaces: %s", data[1])
|
||||
}
|
||||
prettyName = prettyNames[0]
|
||||
}
|
||||
}
|
||||
if prettyName != "" {
|
||||
return prettyName, nil
|
||||
}
|
||||
// If not set, defaults to PRETTY_NAME="Linux"
|
||||
// c.f. http://www.freedesktop.org/software/systemd/man/os-release.html
|
||||
return "Linux", nil
|
||||
}
|
||||
|
||||
// IsContainerized returns true if we are running inside a container.
|
||||
|
|
|
@ -10,9 +10,74 @@ import (
|
|||
)
|
||||
|
||||
func TestGetOperatingSystem(t *testing.T) {
|
||||
var (
|
||||
backup = etcOsRelease
|
||||
ubuntuTrusty = []byte(`NAME="Ubuntu"
|
||||
var backup = etcOsRelease
|
||||
|
||||
invalids := []struct {
|
||||
content string
|
||||
errorExpected string
|
||||
}{
|
||||
{
|
||||
`PRETTY_NAME=Source Mage GNU/Linux
|
||||
PRETTY_NAME=Ubuntu 14.04.LTS`,
|
||||
"PRETTY_NAME needs to be enclosed by quotes if they have spaces: Source Mage GNU/Linux",
|
||||
},
|
||||
{
|
||||
`PRETTY_NAME="Ubuntu Linux
|
||||
PRETTY_NAME=Ubuntu 14.04.LTS`,
|
||||
"PRETTY_NAME is invalid: invalid command line string",
|
||||
},
|
||||
{
|
||||
`PRETTY_NAME=Ubuntu'
|
||||
PRETTY_NAME=Ubuntu 14.04.LTS`,
|
||||
"PRETTY_NAME is invalid: invalid command line string",
|
||||
},
|
||||
{
|
||||
`PRETTY_NAME'
|
||||
PRETTY_NAME=Ubuntu 14.04.LTS`,
|
||||
"PRETTY_NAME needs to be enclosed by quotes if they have spaces: Ubuntu 14.04.LTS",
|
||||
},
|
||||
}
|
||||
|
||||
valids := []struct {
|
||||
content string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
`NAME="Ubuntu"
|
||||
PRETTY_NAME_AGAIN="Ubuntu 14.04.LTS"
|
||||
VERSION="14.04, Trusty Tahr"
|
||||
ID=ubuntu
|
||||
ID_LIKE=debian
|
||||
VERSION_ID="14.04"
|
||||
HOME_URL="http://www.ubuntu.com/"
|
||||
SUPPORT_URL="http://help.ubuntu.com/"
|
||||
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`,
|
||||
"Linux",
|
||||
},
|
||||
{
|
||||
`NAME="Ubuntu"
|
||||
VERSION="14.04, Trusty Tahr"
|
||||
ID=ubuntu
|
||||
ID_LIKE=debian
|
||||
VERSION_ID="14.04"
|
||||
HOME_URL="http://www.ubuntu.com/"
|
||||
SUPPORT_URL="http://help.ubuntu.com/"
|
||||
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`,
|
||||
"Linux",
|
||||
},
|
||||
{
|
||||
`NAME=Gentoo
|
||||
ID=gentoo
|
||||
PRETTY_NAME="Gentoo/Linux"
|
||||
ANSI_COLOR="1;32"
|
||||
HOME_URL="http://www.gentoo.org/"
|
||||
SUPPORT_URL="http://www.gentoo.org/main/en/support.xml"
|
||||
BUG_REPORT_URL="https://bugs.gentoo.org/"
|
||||
`,
|
||||
"Gentoo/Linux",
|
||||
},
|
||||
{
|
||||
`NAME="Ubuntu"
|
||||
VERSION="14.04, Trusty Tahr"
|
||||
ID=ubuntu
|
||||
ID_LIKE=debian
|
||||
|
@ -20,24 +85,28 @@ PRETTY_NAME="Ubuntu 14.04 LTS"
|
|||
VERSION_ID="14.04"
|
||||
HOME_URL="http://www.ubuntu.com/"
|
||||
SUPPORT_URL="http://help.ubuntu.com/"
|
||||
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`)
|
||||
gentoo = []byte(`NAME=Gentoo
|
||||
ID=gentoo
|
||||
PRETTY_NAME="Gentoo/Linux"
|
||||
ANSI_COLOR="1;32"
|
||||
HOME_URL="http://www.gentoo.org/"
|
||||
SUPPORT_URL="http://www.gentoo.org/main/en/support.xml"
|
||||
BUG_REPORT_URL="https://bugs.gentoo.org/"
|
||||
`)
|
||||
noPrettyName = []byte(`NAME="Ubuntu"
|
||||
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`,
|
||||
"Ubuntu 14.04 LTS",
|
||||
},
|
||||
{
|
||||
`NAME="Ubuntu"
|
||||
VERSION="14.04, Trusty Tahr"
|
||||
ID=ubuntu
|
||||
ID_LIKE=debian
|
||||
VERSION_ID="14.04"
|
||||
HOME_URL="http://www.ubuntu.com/"
|
||||
SUPPORT_URL="http://help.ubuntu.com/"
|
||||
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`)
|
||||
)
|
||||
PRETTY_NAME='Ubuntu 14.04 LTS'`,
|
||||
"Ubuntu 14.04 LTS",
|
||||
},
|
||||
{
|
||||
`PRETTY_NAME=Source
|
||||
NAME="Source Mage"`,
|
||||
"Source",
|
||||
},
|
||||
{
|
||||
`PRETTY_NAME=Source
|
||||
PRETTY_NAME="Source Mage"`,
|
||||
"Source Mage",
|
||||
},
|
||||
}
|
||||
|
||||
dir := os.TempDir()
|
||||
etcOsRelease = filepath.Join(dir, "etcOsRelease")
|
||||
|
@ -47,22 +116,24 @@ BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`)
|
|||
etcOsRelease = backup
|
||||
}()
|
||||
|
||||
for expect, osRelease := range map[string][]byte{
|
||||
"Ubuntu 14.04 LTS": ubuntuTrusty,
|
||||
"Gentoo/Linux": gentoo,
|
||||
"": noPrettyName,
|
||||
} {
|
||||
if err := ioutil.WriteFile(etcOsRelease, osRelease, 0600); err != nil {
|
||||
for _, elt := range invalids {
|
||||
if err := ioutil.WriteFile(etcOsRelease, []byte(elt.content), 0600); err != nil {
|
||||
t.Fatalf("failed to write to %s: %v", etcOsRelease, err)
|
||||
}
|
||||
s, err := GetOperatingSystem()
|
||||
if s != expect {
|
||||
if expect == "" {
|
||||
t.Fatalf("Expected error 'PRETTY_NAME not found', but got %v", err)
|
||||
} else {
|
||||
t.Fatalf("Expected '%s', but got '%s'. Err=%v", expect, s, err)
|
||||
if err == nil || err.Error() != elt.errorExpected {
|
||||
t.Fatalf("Expected an error %q, got %q (err: %v)", elt.errorExpected, s, err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, elt := range valids {
|
||||
if err := ioutil.WriteFile(etcOsRelease, []byte(elt.content), 0600); err != nil {
|
||||
t.Fatalf("failed to write to %s: %v", etcOsRelease, err)
|
||||
}
|
||||
s, err := GetOperatingSystem()
|
||||
if err != nil || s != elt.expected {
|
||||
t.Fatalf("Expected %q, got %q (err: %v)", elt.expected, s, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue