diff --git a/aaparser/aaparser.go b/aaparser/aaparser.go index 2d34643..507298f 100644 --- a/aaparser/aaparser.go +++ b/aaparser/aaparser.go @@ -14,13 +14,13 @@ const ( ) // GetVersion returns the major and minor version of apparmor_parser. -func GetVersion() (int, int, error) { +func GetVersion() (int, error) { output, err := cmd("", "--version") if err != nil { - return -1, -1, err + return -1, err } - return parseVersion(string(output)) + return parseVersion(output) } // LoadProfile runs `apparmor_parser -r -W` on a specified apparmor profile to @@ -47,30 +47,46 @@ func cmd(dir string, arg ...string) (string, error) { } // parseVersion takes the output from `apparmor_parser --version` and returns -// the major and minor version for `apparor_parser`. -func parseVersion(output string) (int, int, error) { +// a representation of the {major, minor, patch} version as a single number of +// the form MMmmPPP {major, minor, patch}. +func parseVersion(output string) (int, error) { // output is in the form of the following: // AppArmor parser version 2.9.1 // Copyright (C) 1999-2008 Novell Inc. // Copyright 2009-2012 Canonical Ltd. + lines := strings.SplitN(output, "\n", 2) words := strings.Split(lines[0], " ") version := words[len(words)-1] // split by major minor version v := strings.Split(version, ".") - if len(v) < 2 { - return -1, -1, fmt.Errorf("parsing major minor version failed for output: `%s`", output) + if len(v) == 0 || len(v) > 3 { + return -1, fmt.Errorf("parsing version failed for output: `%s`", output) } + // Default the versions to 0. + var majorVersion, minorVersion, patchLevel int + majorVersion, err := strconv.Atoi(v[0]) if err != nil { - return -1, -1, err - } - minorVersion, err := strconv.Atoi(v[1]) - if err != nil { - return -1, -1, err + return -1, err } - return majorVersion, minorVersion, nil + if len(v) > 1 { + minorVersion, err = strconv.Atoi(v[1]) + if err != nil { + return -1, err + } + } + if len(v) > 2 { + patchLevel, err = strconv.Atoi(v[2]) + if err != nil { + return -1, err + } + } + + // major*10^5 + minor*10^3 + patch*10^0 + numericVersion := majorVersion*1e5 + minorVersion*1e3 + patchLevel + return numericVersion, nil } diff --git a/aaparser/aaparser_test.go b/aaparser/aaparser_test.go index 4befa0a..69bc8d2 100644 --- a/aaparser/aaparser_test.go +++ b/aaparser/aaparser_test.go @@ -5,9 +5,8 @@ import ( ) type versionExpected struct { - output string - major int - minor int + output string + version int } func TestParseVersion(t *testing.T) { @@ -18,8 +17,7 @@ Copyright (C) 1999-2008 Novell Inc. Copyright 2009-2012 Canonical Ltd. `, - major: 2, - minor: 10, + version: 210000, }, { output: `AppArmor parser version 2.8 @@ -27,8 +25,7 @@ Copyright (C) 1999-2008 Novell Inc. Copyright 2009-2012 Canonical Ltd. `, - major: 2, - minor: 8, + version: 208000, }, { output: `AppArmor parser version 2.20 @@ -36,8 +33,7 @@ Copyright (C) 1999-2008 Novell Inc. Copyright 2009-2012 Canonical Ltd. `, - major: 2, - minor: 20, + version: 220000, }, { output: `AppArmor parser version 2.05 @@ -45,21 +41,33 @@ Copyright (C) 1999-2008 Novell Inc. Copyright 2009-2012 Canonical Ltd. `, - major: 2, - minor: 5, + version: 205000, + }, + { + output: `AppArmor parser version 2.9.95 +Copyright (C) 1999-2008 Novell Inc. +Copyright 2009-2012 Canonical Ltd. + +`, + version: 209095, + }, + { + output: `AppArmor parser version 3.14.159 +Copyright (C) 1999-2008 Novell Inc. +Copyright 2009-2012 Canonical Ltd. + +`, + version: 314159, }, } for _, v := range versions { - major, minor, err := parseVersion(v.output) + version, err := parseVersion(v.output) if err != nil { t.Fatalf("expected error to be nil for %#v, got: %v", v, err) } - if major != v.major { - t.Fatalf("expected major version to be %d, was %d, for: %#v\n", v.major, major, v) - } - if minor != v.minor { - t.Fatalf("expected minor version to be %d, was %d, for: %#v\n", v.minor, minor, v) + if version != v.version { + t.Fatalf("expected version to be %d, was %d, for: %#v\n", v.version, version, v) } } }