Merge pull request #16692 from vdemeester/16690-fix-etc-osrelease-panic
Fix panic in parsing /etc/os-release
This commit is contained in:
commit
5ecd79236b
2 changed files with 131 additions and 36 deletions
|
@ -3,9 +3,14 @@
|
||||||
package operatingsystem
|
package operatingsystem
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mattn/go-shellwords"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -18,15 +23,34 @@ var (
|
||||||
|
|
||||||
// GetOperatingSystem gets the name of the current operating system.
|
// GetOperatingSystem gets the name of the current operating system.
|
||||||
func GetOperatingSystem() (string, error) {
|
func GetOperatingSystem() (string, error) {
|
||||||
b, err := ioutil.ReadFile(etcOsRelease)
|
osReleaseFile, err := os.Open(etcOsRelease)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if i := bytes.Index(b, []byte("PRETTY_NAME")); i >= 0 {
|
defer osReleaseFile.Close()
|
||||||
b = b[i+13:]
|
|
||||||
return string(b[:bytes.IndexByte(b, '"')]), nil
|
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())
|
||||||
|
}
|
||||||
|
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]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return "", errors.New("PRETTY_NAME not found")
|
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.
|
// IsContainerized returns true if we are running inside a container.
|
||||||
|
|
|
@ -10,9 +10,74 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetOperatingSystem(t *testing.T) {
|
func TestGetOperatingSystem(t *testing.T) {
|
||||||
var (
|
var backup = etcOsRelease
|
||||||
backup = etcOsRelease
|
|
||||||
ubuntuTrusty = []byte(`NAME="Ubuntu"
|
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"
|
VERSION="14.04, Trusty Tahr"
|
||||||
ID=ubuntu
|
ID=ubuntu
|
||||||
ID_LIKE=debian
|
ID_LIKE=debian
|
||||||
|
@ -20,24 +85,28 @@ PRETTY_NAME="Ubuntu 14.04 LTS"
|
||||||
VERSION_ID="14.04"
|
VERSION_ID="14.04"
|
||||||
HOME_URL="http://www.ubuntu.com/"
|
HOME_URL="http://www.ubuntu.com/"
|
||||||
SUPPORT_URL="http://help.ubuntu.com/"
|
SUPPORT_URL="http://help.ubuntu.com/"
|
||||||
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`)
|
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`,
|
||||||
gentoo = []byte(`NAME=Gentoo
|
"Ubuntu 14.04 LTS",
|
||||||
ID=gentoo
|
},
|
||||||
PRETTY_NAME="Gentoo/Linux"
|
{
|
||||||
ANSI_COLOR="1;32"
|
`NAME="Ubuntu"
|
||||||
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"
|
|
||||||
VERSION="14.04, Trusty Tahr"
|
VERSION="14.04, Trusty Tahr"
|
||||||
ID=ubuntu
|
ID=ubuntu
|
||||||
ID_LIKE=debian
|
ID_LIKE=debian
|
||||||
VERSION_ID="14.04"
|
PRETTY_NAME='Ubuntu 14.04 LTS'`,
|
||||||
HOME_URL="http://www.ubuntu.com/"
|
"Ubuntu 14.04 LTS",
|
||||||
SUPPORT_URL="http://help.ubuntu.com/"
|
},
|
||||||
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`)
|
{
|
||||||
)
|
`PRETTY_NAME=Source
|
||||||
|
NAME="Source Mage"`,
|
||||||
|
"Source",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`PRETTY_NAME=Source
|
||||||
|
PRETTY_NAME="Source Mage"`,
|
||||||
|
"Source Mage",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
dir := os.TempDir()
|
dir := os.TempDir()
|
||||||
etcOsRelease = filepath.Join(dir, "etcOsRelease")
|
etcOsRelease = filepath.Join(dir, "etcOsRelease")
|
||||||
|
@ -47,21 +116,23 @@ BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"`)
|
||||||
etcOsRelease = backup
|
etcOsRelease = backup
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for expect, osRelease := range map[string][]byte{
|
for _, elt := range invalids {
|
||||||
"Ubuntu 14.04 LTS": ubuntuTrusty,
|
if err := ioutil.WriteFile(etcOsRelease, []byte(elt.content), 0600); err != nil {
|
||||||
"Gentoo/Linux": gentoo,
|
|
||||||
"": noPrettyName,
|
|
||||||
} {
|
|
||||||
if err := ioutil.WriteFile(etcOsRelease, osRelease, 0600); err != nil {
|
|
||||||
t.Fatalf("failed to write to %s: %v", etcOsRelease, err)
|
t.Fatalf("failed to write to %s: %v", etcOsRelease, err)
|
||||||
}
|
}
|
||||||
s, err := GetOperatingSystem()
|
s, err := GetOperatingSystem()
|
||||||
if s != expect {
|
if err == nil || err.Error() != elt.errorExpected {
|
||||||
if expect == "" {
|
t.Fatalf("Expected an error %q, got %q (err: %v)", elt.errorExpected, s, err)
|
||||||
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)
|
|
||||||
}
|
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